我创建了以下内容,以便在超时时执行多个异步任务。我正在寻找能够从任务中提取结果的东西 - 只需要那些超过超时的结果,无论其他任务是否未能完成(简化):
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:请参阅我对this问题的回答。
答案 0 :(得分:3)
我无法使用我的psychic debugging来理解为什么你的代码“导致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>>[]
),这样就可以从这些任务中实际返回结果。< / LI>
await
之后,我们需要过滤掉返回我们超时任务的WhenAny
次调用,因为那里使用string.Empty
没有结果(只有completedTasks.Where(task => task != timeoutTask)
)。< / LI>
P.S :我也answered that question我会(令人惊讶地)建议您使用我的解决方案。
注意:使用Task.Result
属性isn't advisable。你应该await
代替它(即使知道它已经完成)