繁体   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