2011-09-29 148 views
4

我有一個啓動各種對象(類庫)的C#Windows服務。這些對象中的每一個都有自己的「處理」邏輯,通過使用ThreadPool來啓動多個長時間運行的處理線程。我有一個例子,就像這樣:ThreadPool不立即啓動新線程

System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(WorkerThread_Processing)); 

這很好。我的應用程序沒有問題,我的線程運行良好。現在

,進行迴歸測試,我開始那些相同的對象,但是從C#控制檯應用程序,而不是Windows服務。它調用相同的確切代碼(因爲它調用的是相同的對象),但WorkerThread_Processing方法在啓動前延遲20秒。

我走了,並從ThreadPool切換到Thread,問題就消失了。這裏會發生什麼?我知道我沒有超過MaxThreads(我最多開始20個線程)。

+0

這絕對不應該發生,不發生在我身上。您的控制檯應用程序是否在執行其他任務如果你創建了一個全新的控制檯應用程序,並把'ThreadPool.QueueUserWorkItem(o => Console.WriteLine(「test」));'它做同樣的事情? – RandomEngy

+1

另外,如果你想看看ThreadPool在做什麼,我建議運行Process Explorer並留意進程中的線程。你可以看到有多少線程池線程正在啓​​動。如果您的操作需要很長時間才能完成,則可能需要一段時間才能增加20個線程。 – RandomEngy

回答

13

ThreadPool是專門用於長期運行的項目(更具體地說,你甚至不需要啓動新線程時使用ThreadPool,其目的是爲了在有限數量的傳播任務線程)。

如果你的任務是長期運行的,你要麼把它分解成被提上ThreadPool邏輯部分(或使用新的Task框架),或旋轉起來自己Thread對象。

至於爲什麼您遇到的延遲,在MSDN Documentation for the ThreadPool class說以下內容:

作爲其線程管理戰略的一部分,在創建線程之前線程池延遲。因此,當一些任務在短時間內排隊,也可以將所有的任務都開始前一個顯著延遲。

你只知道ThreadPool未達到其最大線程算,而不是多少個線程(如果有的話),它實際上已經閒置。

+0

好的,謝謝你的信息!我將用Thread對象替換它們並查看Task對象以供將來開發。謝謝! – MattW

+2

但是,爲什麼這會導致延遲,如果有(假設)池中剩餘的空閒線程?我同意這個結論,但是沒有找到答案令人滿意地回答* why。 – 2011-09-29 17:06:57

+2

@pst:你不知道有留在池中自由線程,你知道'ThreadPool'還沒有達到線程其* *最大數量。根據[MSDN文檔](http://msdn.microsoft.com/en-us/library/0ka9477y(V = VS.95)的.aspx)時,'ThreadPool'將延遲創建新線程,因此添加幾個項立刻幾乎保證會拖延。看我的編輯。謝謝! –

1

線程池的線程值的最大數量是它可以創建的最大數量。這不是已經創建的最大數量。線程池有防止它瞬間旋轉起來一大堆線程的邏輯。

如果調用快速連續ThreadPool.QueueUserWorkItem 10倍,線程池不會立即創建10個線程。它會啓動線程,延遲,啓動另一個,等等。

我似乎記得延遲是500毫秒,但我找不到要驗證的文檔。

這就是:The Managed Thread Pool

線程池有開始新的空閒線程之前內置的延遲(半秒在.NET Framework 2.0版)。如果您的應用程序 定期在很短的時間開始多任務,小 增加空閒線程的數量可以產生吞吐量顯著 增加。設置空閒線程數量過高 不必要地消耗系統資源。

您可以控制使用GetMinThreads和SetMinThreads

請注意,這句話是從.NET 3.5版本的文檔中所採取的線程池 保持空閒的線程數。 .NET 4.0版本沒有提到延遲。

+2

需要注意的一點是'ThreadPool.SetMinThreads'實際上不會增加​​線程池中維護的空閒線程的數量。它只是意味着雖然實際的線程數量低於該數量,但線程池將按需創建新線程,而不是等待先前的線程完成。 – RandomEngy