3

我有這個示例代碼。並行處理密集IO功能

List<Dictionary<string,string>> objects = new List<Dictionary<string,string>>(); 

foreach (string url in urls) 
{ 
    objects.add(processUrl(url)) 
} 

我需要處理的URL,processUrl下加載頁面和運行許多正則表達式來提取一些信息,並返回一個「C#JSON像」對象,所以我想在平行,並在結束時運行這個我需要一個對象的列表,所以我需要等待所有的任務來繼續過程,我該如何做到這一點?我舉了很多例子,但都沒有挽回回報。

問候

回答

2

是否這樣?

var results = urls.AsParallel().Select(processUrl).ToList(); 

隨着Parallel

Parallel.ForEach(
    urls, 
    url => 
    { 
     var result = processUrl(url); 
     lock (syncOjbect) 
      objects.Add(result); 
    }; 

var objects = new ConcurrentBag<Dictionary<string,string>>(); 
Parallel.ForEach(urls, url => objects.Add(processUrl(url))); 
var result = objects.ToList(); 

或任務:

var tasks = urls 
    .Select(url => Task.Factory.StartNew(() => processUrl(url))) 
    .ToArray(); 

Task.WaitAll(tasks); 
var restuls = tasks.Select(arg => arg.Result).ToList(); 
+1

我沒有在Parallel.ForEach的主體中使用鎖,而是使用具有localInit和localFinally的重載,並在localFinally中彙總所有結果。這樣你就不會鎖定每個操作,每個線程只有一次。在localInit中放置一個空列表,添加到本地而不鎖定在主體中,並最終收集。 – vcsjones 2011-06-12 02:22:52

+0

這些選項都沒有提供限制同時執行任務總數的方法。 – 2011-06-12 05:41:12

+0

@Rick Sladkey - 不知道我理解你的評論。所有3個選項都有一種方法來限制同時執行的任務的數量,我沒有在代碼中顯示它,因爲這沒有被問到。 – 2011-06-12 05:53:56

0

首先,重構爲

processUrl(url, objects); 

交任務負責添加結果到列表中。

然後添加鎖定,這樣兩個並行任務不會嘗試完全同時使用結果列表。


注:async在.NET的下一個版本的支持將讓這個簡單的。

+0

downvote的原因是什麼? – 2011-06-12 02:42:34

-1

您可以使用PLINQ擴展,這需要.NET 4.0

System.Threading.Tasks.Parallel 
      .ForEach(urls, url => { 
      var result = processUrl(url); 
      lock(objects) 
      { 
        objects.Add(result); 
      } 
      }); 
+3

'列表'不是線程安全的。 – 2011-06-12 02:13:27

+3

只要物品處於類似列表的集合(例如數組或列表中),就可以使用Parallel.For。然後可以使用循環索引將結果輸出到數組槽中。這將是線程安全的,不需要鎖。 – bobbymcr 2011-06-12 02:21:51