2015-12-19 50 views
1

我知道如何编写Parallel.ForParallel.ForEach循环。下面是他们两个的示例代码:如何依次执行Parallel.For循环和Parallel.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使用什么算法/策略来在多个内核上调度代码?它的产品从并行编程中脱颖而出。

+0

采取他们将按顺序执行,第一** **对于然后** **的ForEach。但是他们在自己范围内的结果并不能保证按顺序排列。 – Shaharyar

+0

如果你想顺序执行,使用'for'和'foreach',集合的任何先决条件将降低它在'Parallel'中运行的性能,甚至可能比顺序循环慢 –

回答

0

线程运行并行并按顺序没有意义。

如果Thread 3之前完成Thread 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