2011-05-01 106 views
0

我會馬上說出這個問題。我是線程的業餘愛好者。我是一個高級c#web開發人員,但我有一個項目,需要我填充很多需要很長時間填充的對象,因爲它們需要填充WebRequests響應來填充。我有一切工作沒有線程,但它運行速度不夠我的要求。我想將所有內容都傳遞給ThreadPool以便爲我管理線程,因爲我可能會同時排隊20,000個線程,原因很明顯。我不想打一個網站,要求一次填充所有請求。將對象傳遞給線程並在線程運行後將其取回

我想這樣做是在對象通過,填充它,然後在主線程添加集合一旦填充。然後,一旦所有對象都被填充,繼續執行程序。我不知道有多少物體需要填充,直到它們全部填充。

我的問題...這樣做的最佳方法是什麼?

這裏是我試圖加快循環:

foreach (HElement hElement in repeatingTag.RunRepeatingTagInstruction()) 
{ 
    object newObject = Activator.CreateInstance(currentObject.GetType().GetGenericArguments()[0]); 
    List<XElement> ordering = GetOrdering(tagInstructions.Attribute("type").Value); 
    RunOrdering(ordering, newObject, hElement); 
    MethodInfo method = currentObject.GetType().GetMethod("Add"); 
    method.Invoke(currentObject, new[] { newObject }); 
} 

我不知道對象是什麼事前,所以我創建一個使用激活它。 RunOrdering方法遍歷我傳遞的指示信息,告訴它如何填充對象。然後我將它添加到集合中。此外,對象本身可能具有需要此方法運行並填充其數據的屬性。

+2

如果您的程序的目的是發出20,000個Web請求,那麼它並不受限於您將這些任務分配給CPU內核的程度,而是受網絡帶寬的限制。通過並行執行2-5個請求,你可能會獲得很小的加速,但是在這之上並沒有太大的改進。您需要的是某種「調度程序」,它保留未完成任務的列表,並始終保持少量並行運行的任務。任務將結果寫入共享集合。調度程序在所有任務完成時設置一個信號。 – dtb 2011-05-01 20:53:27

回答

2

由於您可能需要等待它們全部完成,所有您需要的是Parallel.ForEach()或同等產品。和一個線程安全的集合。請注意,對於I/O密集型任務,您希望限制線程的數量。在任何情況下,20.00線程都會瘋狂。

但我們需要看到更多細節(代碼)。請注意,沒有「主線程中的集合」這樣的東西。

+1

無論如何,你應該添加代碼和其他信息的問題。 – 2011-05-01 21:14:59

+0

我試着改變我的foreach循環來使用Parallel.ForEach,它似乎在工作一點點,但我得到一個錯誤,說它無法更新集合。我假設這是由於Add方法試圖與另一個線程同時更新集合。有沒有辦法檢查鎖定情況? (我可能沒有這個正確的術語) – light 2011-05-01 21:57:02

+0

是的。我不知道RunOrdering()在做什麼,但是你必須儘可能地驗證每個Task是否獨立,並且在需要共享的地方使用'lock'。 – 2011-05-01 22:03:12

1

填充很多是需要 長的時間來填充,因爲它們需要 WebRequests和響應

避免線程,如果你正在做的請求對象。 兩個線程之後沒有加速,僅存在於兩個線程中。 大量的白白浪費。

+0

我也提出了這個答案,因爲它似乎沒有更快地運行,並且實施起來有點痛苦。 – light 2011-05-01 22:51:02

+0

我知道,已經在那裏,也有同樣的失望:/ – 2011-05-02 00:20:19

0

夫婦的建議:

如果您使用Tasks而不是.NET 4的嘗試。你可以更好地控制調度。儘量不共享任何對象,使他們不變的,所有的警告和best practices關於同步,共享數據等

其次,你可能要考慮一個徹頭徹尾的流程解決方案一樣message queues的(XMQ產品或窮人的數據庫表作爲隊列),所以如果需要的話,你將有機會將任務分配到多臺機器上。