如何平行和连续地处理集合中的项目

D J*_*D J 2 .net c# multithreading task-parallel-library

我有一个集合,其中包含要处理的元素,最多只能处理四个元素.在运行时,所有进程一起启动,所有进程都处于等待状态.一次只处理四个元素.

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

但是,我需要按照它们在集合中的顺序处理元素.

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

我正在使用TPL和C#4.0

Tud*_*dor 5

对于并行性,总是存在定义"按顺序"意味着什么的问题.假设您有100个项目的集合.按"按顺序"按顺序处理它们(按照您的要求)可能意味着:

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

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

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

    在不平衡任务的情况下,这将很快失去原始排序,因为一些线程可能在重任务上落后,但任务将按顺序分配.

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

                   0 1 2 3                
                   4 tasks
         _____________________________
                    barrier
    
                   4 5 6 7                
                   4 tasks
         _____________________________
                    barrier
    
                     etc.
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    虽然您必须确保任务数是4的倍数,否则在最后一次迭代时不会发出屏障信号.

  3. 处理单个任务中的4个项目:您可以创建一个封装原始列表的4个项目的任务对象,然后Parallel.ForEach像第一个案例那样执行简单操作(即每个线程将按顺序处理4个项目作为单个任务的一部分).这将按顺序以4个为一组发出任务,但如果任务花费的时间过长,则可能会导致某些线程滞后.