需要帮助理解 .net 线程池

3

我正在努力理解ThreadPool的作用,这是一个.NET示例:

class Program
{
    static void Main()
    {
        int c = 2;

        // Use AutoResetEvent for thread management

        AutoResetEvent[] arr = new AutoResetEvent[50];

        for (int i = 0; i < arr.Length; ++i)
        {
            arr[i] = new AutoResetEvent(false);
        }

        // Set the number of minimum threads
        ThreadPool.SetMinThreads(c, 4);

        // Enqueue 50 work items that run the code in this delegate function
        for (int i = 0; i < arr.Length; i++)
        {
            ThreadPool.QueueUserWorkItem(delegate(object o)
            {
                Thread.Sleep(100);
                arr[(int)o].Set(); // Signals completion

            }, i);
        }

        // Wait for all tasks to complete
        WaitHandle.WaitAll(arr);
    }
}

这个程序会以每组2个(int c)的方式运行50个“任务”,直到它们全部完成吗?还是我没有真正理解它的作用。


1
你试过运行它并观察发生了什么吗? - Lasse V. Karlsen
这不是很好地解释了SetMinThreads的作用吗?http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setminthreads.aspx ...归根结底,实际上启动的线程数将取决于可用的系统资源,这可能会在每次运行时发生变化。 - James Gaunt
4个回答

3
如果您有一点时间,我非常推荐阅读这篇文章:http://www.albahari.com/threading/。 这是一篇优秀的文章,从基本的线程到并行编程打下了基础。在尝试修改线程池代码之前,我建议您先掌握前两章的基本概念! :)

1
这是一个很棒的链接,关于线程正在发生什么的优秀资源。我完全忘记提到了。太好了!+1 - David Hoerster
我已经阅读并反复阅读了那个内容3天,同时尝试着实现它! - Joe
我们创建了一个多线程服务来处理非常特定的请求,他的Wait-and-Pulse模式解释是非常宝贵的。http://www.albahari.com/threading/part4.aspx#_How_to_Use_Wait_and_Pulse - David Hoerster
对我们来说,我们的轮询服务受到了定期轮询之间进行的大量耗时后台工作的影响。我甚至还没有涉及第4章,只是利用了EAP模式中的后台工作者(.net 3.5)和锁。在这个阶段,我还不太有信心做更多的事情!但是,简明扼要的解释很好。在多次尝试后,我真正开始理解线程处理。 - Joe

1
通过设置线程池的最小线程数,你所要求的.NET运行时做的唯一事情就是请至少分配2个线程给线程池。你并没有要求它仅限于使用2个线程。
因此,你的程序将使用多少个线程是不确定的,这取决于你的系统和许多其他因素。
我进行了一个简单的测试(对你的程序进行了微小的更改,只是跟踪同时进入睡眠调用的线程),在一个运行中达到了4个,另一个运行中达到了3个,在另一个运行中达到了7个,在另一个运行中达到了10个等等。
你真的不应该需要更改线程池大小。
你想要实现什么目标?

0

从 MSDN SetMinThreads 文档中得知:

当需求较低时,线程池线程的实际数量可以低于最小值。

因此,您指定的值并不能保证有2个工作线程处理排队的项。它可能是1个工作线程(因为您正在循环排队它们,可能会在下一个排队之前完成),或者根据系统资源和需要完成的工作量而使用更多线程。

如果您真的想知道发生了什么,请查看像Process Monitor这样的工具。您可以监视进程的线程创建并跟踪它们何时被创建、销毁等。这将真正帮助您了解您的应用程序(以及底层框架)正在做什么。

希望这能帮到您。


0
背景:.NET线程池管理线程的正常方法可能很繁琐。它可以有效地限制由资源争用引起的问题,但是这样做会牺牲线程创建的速度。为了提高使用线程池的工作线程的性能,设计人员允许一种机制,该机制允许创建一定数量的线程而无需经过队列处理。
SetMinThreads()指定应简单创建的线程数“按需”,即仅启动而不检查当前线程计数或排队以缓慢增加。
将发生的情况是,框架将立即创建前两个线程,就像您手动设置并使用Thread.Start启动它们一样。除此之外,在当前MaxThreads计数之内,框架将开始排队请求工作线程,并以指定间隔(默认情况下为250ms,我认为这也可以配置)启动它们,以避免资源冲突。原因是,如果您想象一下循环行为,即启动访问资源的线程,执行某些计算,然后将结果写入其他位置,您可以看到5个线程几乎同时启动将导致尝试到达第一个资源的拥堵。在MaxThreads阈值处,队列停止;直到一个完成,才会创建新线程。

因此,仅凭您的代码本身,将安排50个单独的工作任务,但不是所有50个任务都会同时运行;运行时将允许立即启动两个任务,然后等待250毫秒或直到一个任务结束才开始下一个任务。由于线程将在少于250毫秒的时间内执行和终止,因此您不太可能看到超过2个工作线程同时执行;在创建第三个线程之前的等待永远不会发生,因为“无限制”的工作线程将首先释放,并且正在等待的线程将在其等待时间到期之前被启动,然后使用下一个线程重置时钟。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接