c# - 如何并行和串行处理集合中的项目

标签 c# .net multithreading task-parallel-library

我有一个集合,其中有要处理的元素,最多只能一起处理四个元素。在运行时,所有进程一起启动并且全部进入等待状态。一次仅处理四个元素。

问题是处理元素是随机选择的,因为所有线程都在等待资源释放。意味着第一个元素可以是集合中的最后一个元素。

但是,我需要按照集合中的顺序处理元素。

请告诉我如何实现这一目标?

我正在使用 TPL 和 C# 4.0

最佳答案

对于并行性,始终存在定义“按顺序”含义的问题。假设您有 100 件元素的集合。 “一次按 4 个顺序”处理它们(按照您的要求)可能意味着:

  1. 松散排序:使用 4 个线程,按照原始集合的顺序发出任务。

    在这种情况下,您可以使用:

    ParallelOptions po = new ParallelOptions() { MaxDegreeOfParallelism = 4 };
    Parallel.ForEach(list.AsParallel().AsOrdered(), po,
             (item) =>
             {
                 // code
             });
    

    如果任务不平衡,这将很快失去原始顺序,因为某些线程可能会落后于繁重的任务,但任务将按顺序分配。

  2. 严格排序:按 4 组的顺序处理它们,如下所示:

                   0 1 2 3                
                   4 tasks
         _____________________________
                    barrier
    
                   4 5 6 7                
                   4 tasks
         _____________________________
                    barrier
    
                     etc.
    

    在这种情况下,您可以使用屏障:

    Barrier b = new Barrier(4);
    ParallelOptions po = new ParallelOptions() { MaxDegreeOfParallelism = 4 };
    Parallel.ForEach(list.AsParallel().AsOrdered(), po,
        (item) =>
        {
            // code
            b.SignalAndWait();
        });
    

    尽管您必须确保任务数量是 4 的倍数,否则屏障将不会在最后一次迭代时发出信号。

  3. 在单个任务中处理 4 个项目:您可以创建一个封装原始列表的 4 个项目的任务对象,然后像第一种情况一样执行简单的 Parallel.ForEach (即每个线程将作为单个任务的一部分顺序处理 4 个项目)。这会按顺序以 4 个一组的方式发出任务,但如果任务花费太长时间,可能会再次导致某些线程落后。

关于c# - 如何并行和串行处理集合中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12241983/

相关文章:

c# - 在使用动态更新或插入时,如何使 NHibernate 认为属性总是脏的?

c# - 单元测试:测试的数据库设置

c# - 变量 'variable_name' 未声明或从未分配

.net - ASP.NET Web API(测试版)是否可以与最新的 Mono(稳定版)一起运行?

.net - 使用 PRISM 处理导航的最佳方式是什么?

c# - SharePoint 错误 : Web application at xxxx could not be found

c# - 如何在发送请求后停止加载页面?

java - 如何停止其 run() 没有循环的线程

multithreading - Julia Threads.@threads 比单线程性能慢

python - 从线程内部杀死python线程的方法?