2016-12-06 213 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选项。