2016-12-06 251 views
4

我有大量需要執行的任務(〜1000)。我使用的是四核處理器,所以我想同時處理4個任務。.NET排隊任務(帶異步/等待)

爲了給你一個出發點,下​​面是一些示例代碼。

class Program 
{ 
    public class LongOperation 
    { 
     private static readonly Random RandomNumberGenerator = new Random(0); 
     const int UpdateFrequencyMilliseconds = 100; 

     public int CurrentProgress { get; set; } 

     public int TargetProcess { get; set; } 

     public LongOperation() 
     { 
      TargetProcess = RandomNumberGenerator.Next(
       (int)TimeSpan.FromSeconds(5).TotalMilliseconds/UpdateFrequencyMilliseconds, 
       (int)TimeSpan.FromSeconds(10).TotalMilliseconds/UpdateFrequencyMilliseconds); 
     } 

     public async Task Execute() 
     { 
      while (!IsCompleted) 
      { 
       await Task.Delay(UpdateFrequencyMilliseconds); 
       CurrentProgress++; 
      } 
     } 

     public bool IsCompleted => CurrentProgress >= TargetProcess; 
    } 

    static void Main(string[] args) 
    { 
     Task.Factory.StartNew(async() => 
     { 
      var operations = new List<LongOperation>(); 

      for(var x = 1; x <= 10; x++) 
       operations.Add(new LongOperation()); 

      await ProcessOperations(4, operations); 
     }).Wait(); 
    } 

    public static async Task ProcessOperations(int maxSimultaneous, List<LongOperation> operations) 
    { 
     await Task.WhenAll(operations.Select(x => x.Execute())); 
     // TODO: Process up to 4 operations at a time, until every operation is completed. 
    } 
} 

我想我上會用什麼班了,我怎麼會結構ProcessOperations處理最多同時4次操作,直到所有操作完成後,在一個單一的await-可以輸入一些Task

我在考慮以某種方式使用SemaphoreSlim對象,因爲它似乎適用於限制資源/進程。

+7

您應該查看[TPL DataFlow](https://msdn.microsoft.com/en-us/library/hh228603(v = vs.110).aspx)它是Microsoft爲確切你正試圖做的情況。你只需要用'ActionBlock '替換你的'List '並設置並行限制。 –

+0

我知道我試圖發明一個輪子,只是不知道在哪裏找到它。謝謝! –

回答

3

由於已經有人建議,你需要使用一個方便TPL Dataflow library,有兩大塊,在加工前存儲的信息,然後對他們的實際行動:

// storage 
var operations = new BufferBlock<LongOperation>(); 
// no more than 4 actions at the time 
var actions = new ActionBlock<LongOperation>(x => x.Execute(), 
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 4 }); 

// consume new operations automatically 
operations.LinkTo(actions); 
for(var x = 1; x <= 10; ++x) 
{ 
    // blocking sending 
    operations.Post(new LongOperation()); 
    // awaitable send for async operations 
    // await operations.SendAsync(new LongOperation()); 
} 

您也可以intriduce一些限制的限制,比如當時不超過30個操作,通過設置緩衝區的BoundedCapacity選項。