-1

我有一個需要並行處理的很多項目的IEnumerable。這些項目不是CPU密集型的。 理想情況下,這些項目應該同時執行100個或更多的線程。C# - 並行Foreach緩慢創建線程

我試着用Parallel.ForEach()來做到這一點。這有效,但問題是新線程產生得太慢。在Parallel.Foreach()達到100個線程之前需要很長時間。我知道有一個MaxDegreeOfParallelism屬性,但這是最大值,而不是最小值。

有沒有辦法在100個線程上立即執行foreach? ThreadPool.SetMinThreads是我們寧願避免的,因爲它對整個過程有影響。

是否有自定義分區程序可能的解決方案?

+1

嘛'Parallel.ForEach'使用線程池等劇,但它的規則,所以'SetMinThreads'似乎是唯一的選擇(如果您想使用'Parallel.ForEach'明確)。 – Evk

+0

您能否提供一個示例來演示您的_Processing_ intails。它是IO綁定/ CPU綁定,它是多步驟的過程..等等? – JSteward

+0

但是,如果您的任務不是CPU密集型的(因此 - 主要是IO密集型) - 您可以使用async \ await與SemaphoreSlim結合來限制併發性,例如http://stackoverflow.com/a/10810730/5311735(但不要像那樣使用Task.Run(等待...)。 – Evk

回答

-2

我一直在使用線程池,而不是並行取得了成功:

public static void ThreadForEach<T>(this IEnumerable<T> items, Action<T> action) 
{ 
    var mres = new List<ManualResetEvent>(); 

    foreach (var item in items) 
    { 
     var mre = new ManualResetEvent(false); 

     ThreadPool.QueueUserWorkItem((i) => 
     { 
      action((T)i); 
      mre.Set(); 
     }, item); 

     mres.Add(mre); 
    } 

    mres.ForEach(mre => mre.WaitOne()); 
} 

在我不得不使用此情況下,它跑得比使用Parallel.ForEach嘗試更快。我只能推測這是因爲它試圖使用已經存在的線程(而不是花費開銷來創建新線程)。

+0

您可以使用簡單的PLINQ查詢來完全避免對線程的討論,並完全針對foreach。但是,如果OP的處理以任何方式限制IO,那麼需要轉向同步解決方案。 – JSteward

+0

並行也使用線程池。並行不會中斷。無論如何,你的代碼有很多問題。首先,它使用'List'而不是併發集合。其次,這完全是多餘的。 'await Task.WaitAll(items.Select(it => Task.Run(action(it))。ToArray())'會做同樣的事情 –

+0

最後,'Parallel'意思是* data * parallelism。你需要處理大量的數據,而不是大量的任務,通常你不需要更多的任務,而不是核心來處理每個數據的一個分區,如果這個動作被阻塞了,那麼就錯誤地使用了「Parallel」 –

0

我用5秒的超時時間ping了很多設備。你如何儘可能快地做到這一點,只有4個線程(4個核心)?

我打算假設你的ping設備在局域網上,每一個都可以通過IP地址進行識別和訪問。

namespace PingManyDevices { 

    public class DeviceChecker {     

     public async Task<PingReply[]> CheckAllDevices(IEnumerable<IPAddress> devices) { 
      var pings = devices.Select(address => new Ping().SendPingAsync(address, 5000)); 
      return await Task.WhenAll(pings); 
     } 
     /*** 
     * Maybe push it a little further 
     ***/ 
     public async Task<PingReply[]> CheckAllDevices(IEnumerable<IPAddress> devices) { 
      var pings = devices.AsParallel().Select(address => new Ping().SendPingAsync(address, 5000)); 
      return await Task.WhenAll(pings); 
     }   
    } 
}