5

我想要實現.NET 4助手/實用程序類,它應該根據webtesting工具的url列表檢索HTML頁面源。該解決方案應該具有可擴展性和高性能。如何使用異步webrequests執行多線程

我一直在研究和嘗試不同的解決方案,已經很多天,但無法找到妥善的解決辦法。

基於我實現我的目標是使用使用TPL運行並行異步webrequests理解最好的方法。

爲了擁有完全控制頭等等。我使用HttpWebResponse而不是Web客戶端被包裹HttpWebResponse。在某些情況下,輸出應鏈接到其他任務,因此使用TPL任務可能有意義。

我有許多不同的試驗/方法後,至今取得的成績,

  1. (TPL使用任務)解決方案,看看不同的解決方案的性能級別上實現基本同步,異步(APM)和並行。

  2. 要查看異步並行解決方案的性能,我使用了APM方法BeginGetResponse和BeginRead,並在Parallel.ForEach中運行它。一切正常,我對錶演很滿意。不知何故,我覺得使用簡單的Parallel.ForEach不是一種好的方式,例如我不知道如何使用任務鏈。

  3. 然後我試圖更復雜的系統使用任務使用TaskCompletionSource和迭代器通過APM流迭代包裹APM解決方案。我相信這個解決方案可能是我正在尋找的,但是有一個奇怪的延遲,在6-10之間,這在運行500個URL列表時發生了2-3次。

    基礎上執行已經回到其調用異步獲取在一個循環的延遲情況發生時,該線程的日誌。當執行回到循環時,延遲不會總是發生,只是2-3次,其他時間可以正常工作。看起來循環線程會創建一組任務,這些任務將由其他​​線程處理,而大多數/所有任務都會在循環繼續創建剩餘任務並且其他線程再次處於活動狀態之前延遲(6-8秒) 。

內循環迭代的原理是:

IEnumerable<Task> DoExample(string input) 
    { 
    var aResult = DoAAsync(input); 
    yield return aResult; 
    var bResult = DoBAsync(aResult.Result); 
    yield return bResult; 
    var cResult = DoCAsync(bResult.Result); 
    yield return cResult; 
    … 
    } 

Task t = Iterate(DoExample(「42」)); 

我用System.Net.ServicePointManager.DefaultConnectionLimit和超時使用ThreadPool.RegisterWaitForSingleObject

我的問題解決了連接限制簡直是,這將是最好的方法來實現輔助/實用類,檢索HTML頁面將:

  • 是可擴展的,具有高性能
  • 使用webrequests
  • 很容易鏈接到其他任務
  • 能夠使用超時
  • 使用。NET 4框架

如果您認爲使用APM,TaskCompletionSource和迭代器,我上面介紹的解決方案是好的,我將不勝感激試圖解決延遲問題的任何幫助。

我完全不熟悉C#和Windows開發,所以請不要介意我所嘗試的東西沒有太多意義。

任何幫助將被高度讚賞,因爲沒有得到這個解決方案,我不得不放棄我的測試工具開發。

由於

+0

您能否更詳細地解釋您如何使用迭代器,以及爲什麼您認爲將它作爲迭代器實用? – svick 2012-04-17 09:04:35

+0

在嘗試了各種解決方案後,我最終使用了基於msdn博客上MS專家建議的迭代器。我的解決方案或多或少與博客相同,只是增加了超時和日誌記錄。我沒有任何具體的理由來使用迭代器,並且我願意接受任何有效的解決方案。鏈接到代碼片段:http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/95355648-1fa6-4b2d-a260-954c3421c453/ – Laowai 2012-04-17 09:44:41

回答

0

使用迭代是在預TPL .NET很好的解決方案(例如,協調和併發運行時(CCR)出MS機器人大量使用它們的和有助於激勵TPL)。一個問題是,迭代器本身不會給你你需要的東西 - 你還需要一個調度器來有效地分配工作負載。這是幾乎由Stephen Toub的片段做你鏈接到 - 但請注意,一條線:

enumerator.Current.ContinueWith(recursiveBody, TaskContinuationOptions.ExecuteSynchronously); 

我想你看到的可能與強迫「ExecuteSynchronously」的間歇性問題 - 這可能會導致一個整個可用核心/線程的工作分配不均勻。

看看斯蒂芬提出的一些其他替代方案in his blog article。具體來說,看看只是做一個簡單的ContinueWith()調用鏈會做什麼(如果需要,跟着匹配Unwrap()調用)。語法不會是最漂亮的,但它是最簡單的,並儘可能少地干擾潛在的工作竊取運行時,所以您希望得到更好的結果。

+0

感謝您的建議和意見。我會仔細看看斯蒂芬的博客。 – Laowai 2012-06-21 14:18:44

+0

當然!讓我們知道你發現了什麼... – 2012-06-23 02:38:54