2011-06-08 72 views
3

我剛剛完成了我最複雜和功能最強的WinForms應用程序的日期。它加載一個列表中的任意數量的HTML文件,然後加載一個內容,使用一些正則表達式來匹配一些標籤,並刪除或替換它們(是的,是的,我見過this。它工作得很好,謝謝Cthulu),然後將它寫入磁盤。將使用多個線程加速我的HTML文件處理應用程序?

但是,我注意到約200個文件需要大約30秒來處理,並且在第一個5-10秒之後程序報告爲「不響應」。我假設做this guy did之類的東西並不明智,因爲硬盤是瓶頸。

也許有可能將盡可能多的內存加載到內存中,然後使用線程處理每個內存,然後將它們加載到內存中?

至少,是否會創建一個獨立於UI線程的工作線程來防止「無響應」問題? (This MSDN article covers what I was considering.

我想我是問多線程是否會提供任何速度改進,如果是的話,那麼最好的方法是什麼?

任何幫助或建議非常感謝!

+0

@亨克霍爾特曼我的道歉,WinForms。我將編輯這個問題來反映這一點。 – Omega192 2011-06-08 14:35:00

回答

3

是的,您應該先使用Backgroundworker將您的工作從GUI中分離出來。處理GUI事件永遠不要花費太多時間。瞄準20ms,而不是20s。

然後,作爲獎勵,您可以看到處理(CPU密集型部分)是否可以拆分爲獨立作業並將其作爲TPL任務執行。

沒有足夠的信息來說明是否應該如何做。

+0

+1對於TPL:偉大的庫 – IAbstract 2011-06-08 14:28:31

+0

我在MSDN文章中讀過了20ms規則。這是我第一次編寫需要這麼長時間的應用程序,因此後臺工作者的概念對我來說是全新的。 我會研究TPL,這確實聽起來不錯。謝謝! – Omega192 2011-06-08 14:43:27

+0

查看[本頁](http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx),特別是Completed事件中的if/else if/...。 – 2011-06-08 18:07:58

0

爲什麼不使用StreamReader.ReadAllLines()將每個文件讀入數組,然後處理數組中的每個元素?

+0

我正在使用StreamReader.ReadToEnd()將文件內容讀入單個字符串。你是否認爲我應該創建幾個線程,並讓每個線程都在上述數組的單個元素上工作?我如何將修正後的元素的寫入同步到磁盤? – Omega192 2011-06-08 14:39:23

-1

如果你在GUI線程中做了所有的處理,你的應用程序將會顯示'沒有響應',如果它需要很長時間。在我看來,您應該儘量不要在與GUI相同的線程中執行(廣泛的)處理操作。 另外,你甚至可以爲每個要處理的文件創建一個線程。只要單獨的線程不需要來自彼此的任何數據,這就會大大提高速度。

+0

如果我要爲每個文件創建一個線程,那麼磁盤I/O操作會降低它們的速度。 – Omega192 2011-06-08 14:47:28

+0

但無論如何,永遠不會超過單線程運行的一切權利? – 2011-06-08 14:58:29

+0

你不想爲每個文件創建一個線程。 – IAbstract 2011-06-08 15:45:16

2

線程作業,任務等在大多數情況下會阻止主線程或主線程變得無法響應。不要爲磁盤IO創建多個線程(顯然)。我將專用一個工作線程來將文件從隊列中取出並處理磁盤IO。否則,只有1或2個工作線程才能執行內存中的處理,而主線程可以保持響應。

+0

我一定會考慮做一些事情。謝謝! – Omega192 2011-06-08 14:46:38

2

首先,如果您希望程序保持響應,請將計算移至單獨的線程(將其從UI線程中移除)。

實際性能改進取決於您擁有的處理器數量,而不是線程數量。

所以,如果你有P線程,你可以把工作P工作項目,並得到了一些改進工作。 (Amdahl's Law

您可以使用BackgroundWorker正確劃分工作。:C# BackgroundWorker Tutorial

+0

我不知道BackgroundWorker甚至存在,謝謝你的鏈接! – Omega192 2011-06-08 14:45:58

+0

不是一個很好的教程。 Completed事件錯誤。 – 2011-06-08 18:05:31