等待中的System.AggregateException Task.WhenAll()

时间:2017-11-28 10:28:41

标签: async-await task

我有一个从DB检索行列表的进程,每行必须执行一个长时间运行的列表:

  1. 将文件上传到FTP服务器
  2. 每1分钟检查一次特定文件(基于1中上传创建的文件)是否可用于此类FTP服务器
  3. 下载步骤2中找到的文件,一旦可用
  4. 保存在DB中下载的文件的内容
  5. 我已经实现了一个按照上面提到的顺序执行所有这些步骤的方法:我想要并行多次调用该方法(异步):调用它的次数将取决于在工作流程的开始。

    主要方法的提取如下:

    List<Model> ftpModels = _service.CreateFtpModel(rowsFromDB);
    List<Task> asyncTasks = new List<Task>();
    
    ftpModels.AsParallel().ForAll(p =>
    {
        asyncTasks.Add(DoStepsAsync(p));
    });
    // Wait for all the tasks to finish.
    await Task.WhenAll(asyncTasks.Where(p => p != null));
    

    首先,根据从DB检索到的行创建模型列表, 然后创建一个空的任务列表,然后遍历创建的模型以执行异步方法“DoStepsAsync”,该方法检索要插入到asyncTasks列表中的任务。最后,它为所有任务调用Tasks.WhellAll。

    这种方法通常运行正常,但我碰巧发现有时(随机的线程相关问题)在WhenAll方法上抛出了下一个异常:

    System.AggregateException :发生了一个或多个错误。 ---&GT; System.ArgumentException:tasks参数包含空值。

    这清楚地表明我上述任何任务在执行时都返回null(而不是任务)。然后我读了我正在写的日志,但是我没有发现任何异常,只是流程中断了蓝色,然后进入 System.AggregateException

    我在谷歌上搜索并阅读了很多内容,这个问题发生在:

    至少有一个Task实例被取消了。如果任务被取消,则AggregateException异常在其AggregateException.InnerExceptions集合中包含OperationCanceledException异常。 -要么- 在执行至少一个Task实例期间抛出异常。

    但是没有抛出任何异常,因为我已经相应地实现了try-catch块。因此,我不知道到底发生了什么。

    有什么建议吗?

    只是为了提供有关DoStepsAsync()方法中发生的事情的更多信息,有对FTP客户端的异步调用(线程安全),编写日志和类似的东西。令我惊讶的是,即使使用上面提到的所有捕获块,也没有任何异常被捕获。

    任何建议都非常感谢。

1 个答案:

答案 0 :(得分:0)

发现问题:一旦我通过AsParallel().ForAll遍历模型列表,可能会发生(取决于CPU工作负载)创建的任务(异步)尚未创建但正在被访问通过WhenAll方法(也是异步),因此抛出上面提到的异常。正如我所说,根据CPU工作负载,有时会发生这种情况:为了轻松重现问题,我创建了一个单元测试,可以将问题方法调用多达50次,并且通常在前10次运行中失败。 为了解决这个问题,我已经用AsParallel().ForAll替换了无用的(因为在这种情况下没有带来任何相关的)函数ForEach,因为任务不再发生问题无论CPU工作负载如何,始终按顺序创建(不执行,但异步执行)。代码如下,解决问题:

List<Model> ftpModels = _service.CreateFtpModel(rowsFromDB);
List<Task> asyncTasks = new List<Task>();

ftpModels.ForEach(p =>
{
    asyncTasks.Add(DoStepsAsync(p));
});
// Wait for all the tasks to finish.
await Task.WhenAll(asyncTasks.Where(p => p != null));

我希望将来有助于其他人。