2011-03-02 38 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正在使用的幾個啓發式方法是最優的。