• c#自己实现线程池功能(二)


    介绍

    在上一篇c#自己实现线程池功能(一)中,我们基本实现了一个能够执行的程序。而不能真正的称作线程池。因为是上篇中的代码有个致命的bug那就是没有任务是并非等待,而是疯狂的进行while循环,并试图lock任务链表,这样带来的问题的就是性能相当低下,程序反映速度非常慢(当增加一个新任务后,要过非常久这个job才開始执行)造成的原因就是刚才所说的。

    为了解决问题我们就须要使用某种方法使得程序可以让进程同步。

    方法一

    使用信号量

    我们为了降低对task任务的加锁操作,仅仅有当task不为空时才进行试探。

    我们的信号量就代表的是任务表里面的数量。当s.WaitOne();成功后我们才開始加锁,并取出任务

    while (flag && TaskQueue != null)
                {
                    //等待任务
                    ThreadPoolManager.s.WaitOne();
                    //获取任务
                    lock (TaskQueue)
                    {
                        try
                        {
                            if (TaskQueue.Count > 0)
                                task = TaskQueue.Dequeue();
                            else
                                task = null;
                        }
                        catch (Exception)
                        {
                            task = null;
                        }
                        if (task == null)
                            continue;
                    }
    在ThreadPoolManager类中增加两个变量

    //因为採用信号量须要定义一个
            public int MaxJobNum = 1000;
            public static Semaphore s;

    并在初始化这个类时 初始化信号量 s = new Semaphore(0, MaxJobNum);

    这样就行实现同步

    以下给出一个測试类

     static void Main(string[] args)
            {
                ThreadPoolManager tpm = new ThreadPoolManager(2);
    
                TestTask t1 = new TestTask("task1");
                TestTask t2 = new TestTask("task2");
                TestTask t3 = new TestTask("task3");
                TestTask t4 = new TestTask("task4");
                TestTask t5 = new TestTask("task5");
                TestTask t6 = new TestTask("task6");
                TestTask t7 = new TestTask("task7");
                TestTask t8 = new TestTask("task8");
                TestTask t9 = new TestTask("task9");
    
                tpm.AddTask(t1);
                tpm.AddTask(t2);
                tpm.AddTask(t3);
                tpm.AddTask(t4);
                tpm.AddTask(t5);
                tpm.AddTask(t6);
                tpm.AddTask(t7);
                tpm.AddTask(t8);
                tpm.AddTask(t9);
            }



    方法二

    我们不是用信号量。我们使用AutoResetEvent来实现同步

    第一步。在ThreadPoolManager初始化时候创建一个  locks = new AutoResetEvent(false);
    当AddTask的时候locks.Set();通知等待的操作。

    然后我们对WorkThread的run函数做一个小小的改动
     public void run()
            {
                while (flag && TaskQueue != null)
                {
                    //等待任务
                    //ThreadPoolManager.sep.WaitOne();
    
                    //等待任务
                    while (TaskQueue.Count == 0 && flag)
                    {
                        try
                        {
                            ThreadPoolManager.locks.WaitOne();
                        }
                        catch (Exception)
                        {
                        }
                    }
                    //获取任务
                    lock (TaskQueue)
                    {
                        try
                        {
                            task = TaskQueue.Dequeue();
                        }
                        catch (Exception)
                        {
                            task = null;
                        }
                        if (task == null)
                            continue;
                    }
                    try
                    {
                        task.SetEnd(false);
                        task.StartTask();
                    }
                    catch (Exception)
                    {
                    }
                    try
                    {
                        if (!task.IsEnd())
                        {
                            task.SetEnd(false);
                            task.EndTask();
                        }
                    }
                    catch (Exception)
                    {
                    }
    
                }//end of while
            }
    仅仅有当task列表的数量为0时我们才堵塞,直到AddTask的时候才继续下去

  • 相关阅读:
    VirtualBox下Ubuntu更改分辨率方法
    Asp.Net防止刷新重复提交数据小记
    耻辱名单新成员,腾讯QQ影音违反开源协议遭谴责
    赛门铁克BERS 2010新增Linux备份还原
    开源邮件服务解决方案 iRedMail0.6.0beta1 发布,支持 FreeBSD
    防止ASP.NET按钮多次提交代码
    与省局网站备案管理系统接口规范试行版文件下载地址
    2010预测:开源ERP难有大作为
    ASP.NET对IIS中的虚拟目录进行操作
    C#三种模拟自动登录和提交POST信息的实现方法
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6906834.html
Copyright © 2020-2023  润新知