我想让 Task.WaitAll() 在任何正在运行的任务抛出异常时中断,这样我就不必等待 60 秒才能完成。我如何实现这种行为?如果 WaitAll() 无法实现,是否还有任何其他 C# 功能或解决方法?
Task task1 = Task.Run(() => throw new InvalidOperationException());
Task task2 = ...
...
try
{
Task.WaitAll(new Task[]{task1, task2, ...}, TimeSpan.FromSeconds(60));
}
catch (AggregateException)
{
// If any exception thrown on any of the tasks, break out immediately instead of wait all the way to 60 seconds.
}
最佳答案
以下应该在不改变原始任务代码的情况下完成(未经测试):
static bool WaitAll(Task[] tasks, int timeout, CancellationToken token)
{
var cts = CancellationTokenSource.CreateLinkedTokenSource(token);
var proxyTasks = tasks.Select(task =>
task.ContinueWith(t => {
if (t.IsFaulted) cts.Cancel();
return t;
},
cts.Token,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Current).Unwrap());
return Task.WaitAll(proxyTasks.ToArray(), timeout, cts.Token);
}
请注意,它只跟踪错误的任务(那些抛出的任务)。如果您还需要跟踪取消的任务,请进行以下更改:
if (t.IsFaulted || t.IsCancelled) cts.Cancel();
已更新,正如@svick 在评论中指出的那样,等待任务代理在这里是多余的。他提出了一个改进版本:https://gist.github.com/svick/9992598 .
关于c# - 如果发生任何异常,如何使 Task.WaitAll() 中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22849661/