2010-08-04 71 views
6

我建立了上成千上萬的文件執行工作的應用程序的I/O,然後寫入這些文件複製到磁盤的修改後的副本。我使用的是線程池,但它產卵這麼多線程的PC變得反應遲鈍260個),所以我從250默認下降到50改變最大,這解決了這個問題(應用程序只產卵約60線程總數),但是現在文件已經準備得如此之快,它將用戶界面捆綁到電腦無響應的地步。我可以限制我的C#應用​​程序

有沒有辦法來限制的I/O量 - 我的意思是,我喜歡用50個線程對文件執行的工作,而不是50個線程被處理時,在同一時間寫作。我寧願不重新設計的文件部分的寫作,如果我可以保持它 - 我希望我能限制的I/O(同時)從這個池中的線程可以消費量。

+1

你說「這些文件正在如此迅速地準備就緒,它佔用了用戶界面」。每次文件準備就緒時,UI是否更新?如果是這樣,這可能是真正的問題嗎? – 2010-08-04 17:42:35

回答

4

你真的不需要那麼多線程。磁盤只能支持其最大讀寫吞吐量,如果單個線程專用於IO即讀取或寫入,則該線程可輕鬆實現最大化。你也不能同時讀寫硬盤(雖然操作系統緩存層等很複雜),所以併發線程的讀寫操作可能會產生相反的效果。對於非IO任務,擁有比processor \ cores更多的線程也很少,因爲任何其他線程將花費大量時間等待覈心變得可用,例如,如果您有50個線程和4個內核,則在任何給定時間至少有46個線程將處於空閒狀態。浪費的線程將有助於內存消耗也會導致性能開銷,因爲它們都將爭取在某個時間在覈心上獲得破解,而操作系統必須仲裁這場爭鬥。

更簡單的方法是讓一個線程的工作是讀取文件,然後將數據添加到阻塞隊列(例如參見ConcurrentQueue),同時有一些工作線程正在等待文件數據在隊列中(例如,一個數字線程等於處理器\核心的數量)。這些工作線程會在添加項目時穿過隊列,並在空時阻塞。當工作線程完成一項工作時,它可以將其添加到由讀線程線程或專用寫線程監視的另一個阻塞隊列。它的工作是將文件寫出。

此模式旨在平衡IO和CPU之間的一小部分協作線程,其中IO線程的數量被限制爲物理上能夠被硬盤驅動器的數量,以及多個CPU工作線程對您擁有的處理器\核心數量合理。從本質上講,它將IO和CPU分開,以使事情更可預測。

此外,如果IO真的是問題(而不是大量的線程都相互爭鬥),那麼你可以在你的文件讀寫線程中放置一些暫停(例如Thread.Sleep)來限制他們做了很多工作。

更新

或許爲什麼有擺在首位產生這麼多線程有必要解釋。這是線程池使用的退化情況,並且圍繞排隊具有IO組件的工作項。

線程池從其隊列中執行工作項並監視執行工作項目執行的時間。如果當前正在執行的工作項目需要很長時間才能完成(我認爲內存只有半秒),那麼它將開始向池中添加更多線程,因爲它認爲這將更快更公平地處理隊列。但是,如果附加的併發工作項也在共享磁盤上執行工作IO,那麼磁盤的性能實際上會降低,這意味着工作項需要更長的時間才能執行。由於工作項目執行時間較長,線程池會添加更多線程。這是退化情況,隨着更多線程的添加,性能越來越差。

建議使用信號量必須小心,因爲信號量可能會導致線程池線程阻塞,線程池會看到工作項需要很長時間才能執行,並且它仍然會開始添加更多線程。

+0

ThreadPool根據每個文件的內容執行復雜的計算,並使用ThreadPool調整了這部分過程。LOTS :-) – schmoopy 2010-08-04 19:48:38

+0

@schmoopy我不確定我是否理解你的評論。我熟悉線程池和文件處理,因此我回答了你的問題。詳細我可能會添加... – 2010-08-04 19:51:42

相關問題