18

我運行一個多線程循環的執行過程中更改parallelOptions.MaxDegreeOfParallelism:是否有可能一個Parallel.ForEach

protected ParallelOptions parallelOptions = new ParallelOptions(); 

parallelOptions.MaxDegreeOfParallelism = 2; 
Parallel.ForEach(items, parallelOptions, item => 
{ 
// Loop code here 
}); 

我想並行循環的執行期間改變parallelOptions.MaxDegreeOfParallelism減少或增加一些線程。

parallelOptions.MaxDegreeOfParallelism = 5; 

它似乎並沒有增加線程。有沒有人有任何想法?

+0

你能解釋一下你爲什麼想這樣做嗎?如果需要的話,它已經增加了自己的線程數,直到達到指定的最大值,或者如果合適的話,它將使用更少的線程數。 – 2010-09-13 23:02:06

+1

主要用於在共享服務器上使用太多資源時啓動應用程序。我得到的服務器運行在100%,這降低了服務器上其他應用程序的響應度。 – 2010-09-13 23:04:59

+0

這是一個CPU綁定問題或其他「資源」,如磁盤? – 2010-09-13 23:39:40

回答

3

我不希望在調用ForEach之後可以改變並行度。據我所知,ForEach將確定它可以創建多少個線程,創建多個分區,並創建線程以在這些分區上運行。沒有必要說,「哦,等等,他改變了我們的資源分配,讓我重新分割數組並重新分配線程。」

+0

是的,我確定我同意你的理解,但你能請添加參考鏈接? – 2013-04-16 13:17:07

6

甚至試圖做到這一點的問題是,這是一個難題。對於初學者,您甚至可以如何可靠地觀察CPU和磁盤利用率?很少採樣CPU會對實際發生的情況產生不良影響,並且採樣磁盤利用率更難。其次,什麼是你的任務的粒度,以及你能夠迅速改變正在運行的數字。第三,隨着時間的推移,事情會迅速發生變化,因此您需要對觀察結果應用某種過濾。第四,線程的理想數量將取決於代碼實際運行的CPU。第五,如果你分配太多的線程,你會在它們之間顛簸而不是做有用的工作。

請參閱http://msdn.microsoft.com/en-us/magazine/ff960958.aspx以瞭解.NET中的線程池如何處理決定使用多少個線程的複雜任務。

您也可以使用反射器並查看TPL用於分配線程的代碼並避免不必要的上下文切換 - 這很複雜,甚至不考慮磁盤訪問!

您可以改爲嘗試在低優先級的線程上執行任務(創建自己的TaskScheduler,其優先級低於正常運行線程實際上非常簡單)。至少可以確保您可以運行100%的CPU而不會影響系統的其他部分。與線程優先級混淆本身充滿了問題,但如果這是一個純粹的後臺任務,它可以是直接的,並可能有所幫助。

通常情況下,磁盤利用率是真正的罪魁禍首,當涉及到其他應用程序在一個貪婪的應用程序的痛苦。 Windows可以輕鬆地在應用程序之間分配CPU,但是當涉及相對較慢的磁盤訪問時,這是另一回事。與其試圖動態調整您正在運行的線程數量,您可能需要簡單地調整應用程序的大小,使其不會太頻繁地訪問磁盤。在不改變有多少線程處於活動狀態的情況下,您可以這樣做。

您也可以查看SetPriorityClass作爲通知操作系統的一種方式,即您的進程不像系統上運行的其他應用程序那麼重要,有關更多信息,請參見How can I/O priority of a process be increased?。但是,這假定你的整個過程不那麼重要,而不僅僅是這一部分。

相關問題