如何按顺序执行Parallel.For循环和Parallel.ForEach循环

时间:2015-12-19 11:28:35

标签: c# task-parallel-library

我知道如何编写Parallel.ForParallel.ForEach循环。以下是两者的示例代码:

Parallel.For(0,10, (int i) = > 
{
     Console.Writeline(i);
});  

Parallel.ForEach(fruits, fruit =>  
{  
     Console.WriteLine("Fruit Name: {0}, Thread Id= {1}", fruit, Thread.CurrentThread.ManagedThreadId);      
});

但这两个代码示例的问题是循环不按顺序执行。如何让它们按顺序执行?我从人们那里听说你必须锁定一个物体,然后才有可能。我试过搜索并尝试了很多代码示例但没有用。

此外,我想知道按顺序执行的并行循环的性能是否较小?如果不是,为什么不呢?因为锁定,会导致我拙见的延迟。

至于我对并行编程的理解,调度程序在运行时生成调度。任何人都可以告诉.NET IDE使用什么算法/策略来安排几个核心上的代码?其货物内部出于并行编程。

1 个答案:

答案 0 :(得分:0)

让线程并行和按顺序运行并不合理。

如果Thread 3Thread 1之前完成,会发生什么?如果你要阻止Thread 3并让它等到Thread 1完成,那么使用线程有什么意义呢?

但是,如果您希望按顺序完成批次,则可能但仍然不理想。

我的意思是,如果你有一个运行2个线程的列表[1,2,3,4,5,6,7,8,9,10],你可以确保在任何其他项之前处理12,所以上。要做到这一点,你可以使用这样的东西:

void Main()
{
    var items = Enumerable.Range(1, 100);
    const int numThreads = 4;

    foreach(var batch in items.Batch(numThreads))
    {
        var threads = batch.Select(item => {
            return new Thread(() => Console.WriteLine(item));
        }).ToList();

        threads.ForEach(t => t.Start());
        threads.ForEach(t => t.Join());
    }
}

public static class Ext
{
    public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(
                    this IEnumerable<TSource> source, int size)
    {
        TSource[] bucket = null;
        var count = 0;

        foreach (var item in source)
        {
            if (bucket == null)
                bucket = new TSource[size];

            bucket[count++] = item;
            if (count != size)
                continue;

            yield return bucket;

            bucket = null;
            count = 0;
        }

        if (bucket != null && count > 0)
            yield return bucket.Take(count);
    }
}

批量扩展方法取自this answer