[英]Async Task.WhenAll with timeout - issue with completed tasks accumulating
我创建了以下命令,以便在超时的情况下执行多个异步任务。 我一直在寻找可以从任务中提取结果的东西-仅接受那些超过超时的结果,而不管其余任务是否失败(简化):
TimeSpan timeout = TimeSpan.FromSeconds(5.0);
Task<Task>[] tasksOfTasks =
{
Task.WhenAny(SomeTaskAsync("a"), Task.Delay(timeout)),
Task.WhenAny(SomeTaskAsync("b"), Task.Delay(timeout)),
Task.WhenAny(SomeTaskAsync("c"), Task.Delay(timeout))
};
Task[] completedTasks = await Task.WhenAll(tasksOfTasks);
List<MyResult> = completedTasks.OfType<Task<MyResult>>().Select(task => task.Result).ToList();
我已经在(Web API)服务器中的非静态类中实现了此功能。
这在第一次调用时效果很好,但是其他调用导致completedTasks
从以前对服务器的调用中奇怪地累积了任务(如调试器所示)。 在第二个呼叫中有6个已完成的任务,在第三个呼叫中有9个,依此类推。
我的问题:
PS:请参阅我对这个问题的回答。
我无法进行心理调试来理解为什么您的代码“导致completedTasks
奇怪地累积了先前调用中的任务”,但是它可能确实暴露了您的一些误解。
这是一个基于您的代码的工作示例(使用string
代替MyResult
):
Task<string> timeoutTask =
Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith(_ => string.Empty);
Task<Task<string>>[] tasksOfTasks =
{
Task.WhenAny(SomeTaskAsync("a"), timeoutTask),
Task.WhenAny(SomeTaskAsync("b"), timeoutTask),
Task.WhenAny(SomeTaskAsync("c"), timeoutTask)
};
Task<string>[] completedTasks = await Task.WhenAll(tasksOfTasks);
List<string> results = completedTasks.Where(task => task != timeoutTask).
Select(task => task.Result).ToList();
所以,有什么不同:
WhenAny
呼叫都使用了相同的超时任务。 无需使用更多,它们可以在略有不同的时间完成。 Task<string>
而不是Task
。 WhenAny
调用还返回一个Task<string>
(而tasksOfTasks
为Task<Task<string>>[]
),这将使从这些任务中实际返回结果成为可能。 await
之后,我们需要使用completedTasks.Where(task => task != timeoutTask)
过滤掉返回超时任务的WhenAny
调用,因为那里没有结果(只有string.Empty
completedTasks.Where(task => task != timeoutTask)
。 PS :我也回答了这个问题 ,我( 令人惊讶地 )建议您使用我的解决方案。
注意: 建议不要使用Task.Result
属性。 您应该await
它( 即使您知道它已经完成了 )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.