c# - 如果发生任何异常,如何使 Task.WaitAll() 中断?

标签 c# task-parallel-library task async-await

我想让 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/

相关文章:

c# - 防止并行操作按顺序批处理执行

java - 如何为 java 启用任务标签(TODO,...)?

windows - 触发窗口任务计划程序每天在特定时间之间处理几次

c# - Await Task.WhenAll() 内部任务不等待

c# - 为什么 DbConnection.OpenAsync(CancellationToken) 的默认实现是同步的?

c# - 关于Task、async 和await 的多线程

c# - Powershell 通用 session 并在 Exchange 远程管理 session 中导入此 session

c# - 写入单独表单上的文本框 (C#)

c# - 在 .config 中存储供 SecureString 使用的凭据

c# - 包装 EF 方法