2011-03-02 54 views
2

基本上,我希望一次处理多个线程中的项目列表,而不是一次处理一个项目。 我只想要一次有限数量的线程。 这种方法有意义吗?线程数是唯一选项使用全局变量吗? (下面的伪代码)使用多个有限数量的线程处理项目列表

foreach item in list 
    while thread_count >= thread_max 
     sleep 
    loop 
    start_thread item 
    thread_count++ 
next 

function start_thread(item) 
    do_something_to item 
    thread_count-- 
end function 
+0

这个机制来与OSTB .NET 4.0。 :) – bzlm 2011-03-02 22:07:08

+0

你为什么要控制线程的数量?通过使用[Threadpool](http://msdn.microsoft.com/en-us/library/system.threading.threadpool(v = VS.100).aspx)让框架最优地决定。 – 2011-03-04 08:18:05

+0

因此,我可以运行列表并在每个项目上使用QueueUserWorkItem,而不用担心有多少个线程正在运行?游泳池会为我管理吗?有趣... – 2011-03-04 18:56:30

回答

1

这是有道理的,但我希望你知道,这不是通常的方式做到这一点,除非你有非常具体的性能方面的原因或者是停留在.NET 3.5。通常情况下,您会在列表中的元素上使用Parallel.ForEach,并依靠partitioner将工作划分为适当的块。

即使您没有TPL,将所有工作分开并将每个线程同时处理一大块工作,而不是在线程完成的时候将其零散地分配出去,这会更加地道。按照自己的方式做的唯一原因是,如果您预计某个工作项目所需的时间或多或少是不可预测的,那么您无法事先将工作分开。

(另外,你可以只保留对线程的引用,并检查有多少人还在工作,有多少人完成。这将废除该变量。)

6

我会用PLINQ对于这一点,并指定一个最大程度的并行度,如下所示:

我实际上改变了我对这个问题的回答,因为我意识到你只是想直接处理一个原始列表,而不是做任何其他过滤或映射(Where/Select )。在这种特殊情况下它会更好,通过ParallelOptions使用并行::的ForEach并指定MaxDegreeOfParallelism像这样:

int myMaxDegreeOfParallelism = 4; // read this from config maybe 

Parallel.ForEach(
    list, 
    new ParallelOptions 
    { 
     MaxDegreeOfParallelism = myMaxDegreeOfParallelism 
    } 
    item => 
    { 
     // ... your work here ... 
    }); 

现在,请记住,当你指定这样的一个最大可以防止PLINQ从能够即使它们是可用的,也可以使用更多的资源。所以如果这是在8核心机器上运行,它永远不会使用超过4个核心。相反,仅仅因为你指定了4,并不意味着4保证在任何给定时间同时执行。这一切都取决于TPL正在使用的几个启发式方法是最优的。