簡體   English   中英

產卵工人線程

[英]Spawning worker threads

在C#中,

如何生成多個線程,然后在返回整個結果集之前依次將結果添加到列表中?

什么是最佳做法?

到目前為止,我使用ManualResetEvent來表示線程處理最后一個元素的時間。

但是當它返回時,我需要讓它們按順序合並結果集,這樣我們就不會遇到返回值列表的爭用問題(總結果)。

如果在產生線程之前知道最終的順序(你的“順序”暗示),你可以將索引傳遞給每個線程,並讓它將結果寫入數組中的“槽”。 因此,所有線程都已完成處理(以任何順序),結果將已正確排序,完全無需進行后處理排序。

任務並行庫現在是.NET FrameworkReactive Extensions的一部分,使得這樣的事情變得微不足道。 有一組用於並行化代碼的Parallel構造,以及一組可以與它們一起使用的線程安全的Concurrent{Container}s

下面是使用Parallel.ForConcurrentBag來存儲結果的一組數字的示例。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM