2015-12-19 70 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