【发布时间】:2018-05-11 18:32:07
【问题描述】:
我有一个从数据库中检索行列表的进程,并且每行必须执行一个长时间运行的操作列表:
- 将文件上传到 FTP 服务器
- 每 1 分钟检查一次特定文件(基于 1 中上传的文件创建)在此类 FTP 服务器中是否可用
- 下载第 2 步中找到的文件(一旦可用)
- 将下载的文件内容保存到数据库中
我已经实现了一个方法,它按照上述顺序执行所有这些步骤:我想并行(异步)多次调用该方法:调用它的次数将取决于检索到的行数工作流程的开始。
主要方法的提取如下:
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));
首先,根据从数据库中检索到的行创建模型列表, 然后创建一个空的任务列表,然后遍历创建的模型以执行异步方法“DoStepsAsync”,该方法检索要插入到 asyncTasks 列表中的任务。最后,它为所有任务调用 Tasks.WellAll。
这种方法通常工作正常,但我碰巧发现有时(随机与线程相关的问题)在 WhenAll 方法上抛出下一个异常:
System.AggregateException:出现一个或多个错误。 ---> System.ArgumentException:任务参数包含一个空值。
这清楚地表明,上面的任何任务在执行时都返回了 null(而不是任务)。然后我阅读了我正在写的日志,但我在任何地方都没有发现任何异常,只是流程突然中断,落入 System.AggregateException
我在谷歌上搜索和阅读了很多,这个问题发生在:
至少有一个任务实例被取消。如果任务被取消,则 AggregateException 异常在其 AggregateException.InnerExceptions 集合中包含 OperationCanceledException 异常。 -要么- 在至少一个 Task 实例的执行过程中引发了异常。
但是没有抛出异常,因为我已经相应地实现了 try-catch 块。因此,我不知道到底发生了什么。
有什么建议吗?
只是为了提供更多关于 DoStepsAsync() 方法中发生的事情的信息,对 FTP 客户端(线程安全)进行异步调用,写入日志和类似的东西。真正让我吃惊的是,即使上面提到的所有 catch 块,任何地方都没有捕获到异常。
任何建议都非常感谢。
【问题讨论】:
-
当exception is thrownexception is thrown时你有没有尝试让调试器中断?
-
是的,但在调试模式下不会发生。仅在部署应用程序的服务器中,正如我所说,并非总是如此。
-
asyncTasks.Where(p => p != null))与上面的p不同,它是Task,它可能永远不会为空。您的意思是在ForEach之前过滤空的p吗? -
附带说明,如果您使用
Select来生成asyncTasks集合而不是变异的ForEach,则语法会更简洁,因为在ForEach中运行的唯一命令是List<T>.Add -
异常来自具有“tasks”参数的方法。似乎您的代码 sn-p 不能产生该异常。试着在你的程序中寻找另一个地方,在那里你可以调用 WhenAll、WhenAny 等。不幸的是,异步代码没有提供好的调用堆栈来识别特定的调用。
标签: c# async-await task