2013-02-08 34 views
3

我需要從網站上抓取數據。 我有超過1000個需要訪問的鏈接,之前我將鏈接分成10個線程,並且每個線程都會啓動100個線程。在少數測試用例之後,100個線程是減少檢索內容所需時間的最佳計數爲所有鏈接。我發現.NET 4.0爲開箱即用的多線程提供了更好的支持,但是這是基於您擁有多少內核來完成的,這在我的情況下並不會產生足夠的線程。我想我問的是:什麼是優化1000鏈路拉動的最佳方式。我是否應該使用.ForEach並讓Parallel擴展控制產生的線程數量,或者找到一種方法告訴它有多少個線程來啓動和分配工作?Parallel.ForEach/Multithreading的最佳使用

我之前沒有與Parallel一起工作過,所以也許我的方法可能是錯誤的。

+0

從網站拉鍊接不是一個CPU綁定的任務,因此增加大量的線程可能不會幫助你多少。另外,在大多數當前的硬件上產生100個線程是一個壞主意。看看這個異步。 – 2013-02-08 16:52:37

+0

@BrianRasmussen:對於嚴重網絡IO綁定任務,這不一定是真的。只要線程池沒有耗盡,允許更多的併發請求可能是一件好事。如果您有100個線程並且平均響應時間爲1秒,那麼單個核心繫統上每秒最多隻有100次上下文切換,或者在四核系統上最多隻有25次。當然,這些都是假設的數字,但看起來OP已經嘗試了各種參數,並確定了最適合他的用例和硬件的參數。 – 2013-02-08 16:54:18

+0

@EricJ。這就是爲什麼我說「可能」。無論如何,我仍然會在啓動100個線程之前使用異步解決方案。 – 2013-02-08 16:56:47

回答

3

值得檢查的東西是TPL數據流庫。

DataFlow MSDN上。

Nesting await in Parallel.ForEach

背後Parallel.ForEach整體思路()是,你有一組線程和收集的各個過程的一部分。正如您注意到的,這不適用於您想在異步調用期間釋放線程的異步等待。

此外,演練Creating a Dataflow Pipeline專門設置和處理多個網頁下載。 TPL Dataflow的確是爲這種情況設計的。

+0

這是一個很好的模式。我從鏈接的答案中添加了一個摘要,以便您的答案能夠更好地解決問題。 – 2013-02-08 17:06:29

+0

也有[編寫'ForEachAsync']的方法(http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx),但是IMO Dataflow非常適合這個問題。 +1。 – 2013-02-08 17:17:11

3

一般而言,Parallel.ForEach()在優化線程數方面非常出色。它說明了系統中的內核數量,但也考慮了線程正在做什麼(CPU限制,IO限制,方法運行時間等)。

您可以控制最大程度的並行化,但沒有任何機制可以強制使用更多的線程。

確保您的基準測試是正確的,並且可以以公平的方式進行比較(例如,相同的網站,在開始測量之前允許預熱期,並且由於響應時間差異可能相當高) 。如果經過仔細測量,您自己的線程代碼仍然更快,那麼您可以得出結論,您已針對特定情況優化了.NET,並堅持使用自己的代碼。

0

很難說沒有看你的代碼和收藏是如何定義的,我發現Parallel.Invoke是最靈活的。嘗試msdn? ...聽起來像你正在尋找使用Parallel.For Method (Int32, Int32, Action<Int32, ParallelLoopState>)

4

您可以使用Parallel.ForEach中的MaxDegreeOfParallelism屬性來控制將生成的線程數。

繼承人的代碼片段 -

ParallelOptions opt = new ParallelOptions(); 
opt.MaxDegreeOfParallelism = 5; 

Parallel.ForEach(Directory.GetDirectories(Constants.RootFolder), opt, MyMethod); 
+0

請注意,這僅控制*最大*線程數 - 如果決定如此,系統仍然能夠使用較少的線程。 'MaxDegreesOfParallelism'不是保證,只是一個上限。如果你不在這裏設置一個值,默認是基於核心數量,系統負載等。 – GalacticCowboy 2016-04-25 20:15:38