[英]Spawning worker threads
在C#中,
如何生成多個線程,然后在返回整個結果集之前依次將結果添加到列表中?
什么是最佳做法?
到目前為止,我使用ManualResetEvent來表示線程處理最后一個元素的時間。
但是當它返回時,我需要讓它們按順序合並結果集,這樣我們就不會遇到返回值列表的爭用問題(總結果)。
如果在產生線程之前知道最終的順序(你的“順序”暗示),你可以將索引傳遞給每個線程,並讓它將結果寫入數組中的“槽”。 因此,所有線程都已完成處理(以任何順序),結果將已正確排序,完全無需進行后處理排序。
任務並行庫現在是.NET Framework的Reactive Extensions的一部分,使得這樣的事情變得微不足道。 有一組用於並行化代碼的Parallel
構造,以及一組可以與它們一起使用的線程安全的Concurrent{Container}s
。
下面是使用Parallel.For
和ConcurrentBag
來存儲結果的一組數字的示例。
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace ParallelTest
{
class Program
{
static void Main(string[] args)
{
var results = new ConcurrentBag<int>();
Parallel.For(0, 10, i =>
{
results.Add(i * i);
});
foreach (int i in results)
System.Console.WriteLine(i);
}
}
}
ConcurrentBag
是一個常規的IEnumerable
,你可以看到我正在使用一個常規的,非並行的foreach
來打印結果。
注意:所有這些東西在.NET 4.0中實際上是標准的,如果你想要.NET 3.5,你只需要Rx。
如果您使用的是.Net 4,則可以使用Task類。 這是合並List的示例
Task<List<string>> task1 = new Task<List<string>>(SomeFunction);
Task<List<string>> task2 = new Task<List<string>>(SomeFunction);
task1.Start();
task2.Start();
var taskList = new List<Task<List<string>>> {task1, task2};
Task.WaitAll(taskList.ToArray());
List<string> res = new List<string>();
foreach (Task<List<string>> t in taskList)
{
res.AddRange(t.Result);
}
和你的功能
List<string> SomeFunction()
{
return new List<string>{"1","2"};
}
當您啟動每個線程時,將它傳遞給您的序列標識符和回調方法,並遞增一個指示運行線程總數的計數器。 當每個線程完成時,它調用回調方法,該方法遞減正在運行的線程計數並將結果插入到SortedDictionary
,由序列id鍵入。 當最后一個線程完成時,回調可以指示您的主程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.