Task.WaitAll阻止

时间:2017-07-24 15:19:33

标签: c# async-await

我想同时运行两个任务,其中一个任务有一个Task.Delay()。

即。一个连续运行,一个每15分钟运行一次。

这是我到目前为止所拥有的:

public class ContinousAndAggregatedCheckRunner<T, T2>                                                             
{
   private readonly int _aggregationInterval;
   private readonly List<T> _collectedData;
   private readonly Func<IEnumerable<T>, Task<T2>> _aggregator;
   private readonly Func<Task<IEnumerable<T>>> _collector;
   private CancellationToken _aggregationToken = default(CancellationToken);
   private CancellationToken _collectionToken = default(CancellationToken);

   public ContinousAndAggregatedCheckRunner(Func<IEnumerable<T>, Task<T2>> aggregator,
                                            int aggregationInterval,
                                            Func<Task<IEnumerable<T>>>)
   {
      _aggregator = aggregator;
      _aggregationInterval = aggregationInterval;
      _collector = collector;
      _collectedData = new List<T>();
   }

   public async Task Run()
   {
       Task.WaitAll(Collect(), Aggregate());     
   }

   private async Task Collect()
   {
      while (!_collectionToken.IsCancellationRequested)
      {
          Console.WriteLine($"Collecting {DateTime.Now.ToLongDateString()} {DateTime.Now.ToLongTimeString()}");
          try
          {
             var results = await _collector();
             _collectedData.AddRange(results);
          }
          catch (TaskCanceledException)
          {
              break;
          }
       }
    }

    private async Task Aggregate()
    {
       while (!_aggregationToken.IsCancellationRequested)
       {
         Console.WriteLine("Aggregating");
                try
                {
                    var aggregate = await _aggregator(_collectedData);
                    var taskFactory = new TaskFactory();
                    await taskFactory.StartNew(() => Send(aggregate), _aggregationToken);
                    _collectedData.Clear();
                    await Task.Delay(TimeSpan.FromMinutes(_aggregationInterval), _aggregationToken);
                }
                catch (TaskCanceledException)
                {
                    break;
                }
            }
        }

问题是,它运行收集了一点。然后它进入Aggregate()并且它停止为Task.Delay()然后它Sends()做任何事情。然后它什么也没做。

通过什么都不做,我的意思是Collect()停止执行。

我认为它在某些时候是封锁的。

他们的模式在这里我不见了。我想无限期地运行两个任务,并允许其中一个任务pause达到指定的时间而不影响另一个。

1 个答案:

答案 0 :(得分:4)

有几件事可以解决。

  1. 正如Ben Voigt所说,“WaitAll”真的是一个阻挡者,你最好用WhenAll做一系列任务
  2. 使用Task.Factory.StartNew而不是实例化新的TaskFactory实例
  3. 是值得的。
  4. StartNew可能不是最佳选择,详见https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html