如果引发任何异常,如何在Task.WhenAll上取消并引发异常?

Fer*_*lva 3 c# task task-parallel-library async-await

我在等待使用Task.WhenAll的倍数任务.当其中一个生成异常时,我希望Task.WhenAll(或任何其他等待多个任务的方式)立即取消其他任务并引发异常.

可能吗?

提前致谢

Sco*_*ain 9

取消是合法WhenAll,无法取消线程但你可以传递所有这些CancellationToken并在你获得异常时触发令牌.

CancellationTokenSource cts = new CancellationTokenSource();

var task1 = Func1Async(cts.Token);
task1.ContinueWith(task => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
var task2 = Func2Async(cts.Token);
task2.ContinueWith(task => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
var task3 = Func3Async(cts.Token);
task3.ContinueWith(task => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);

await Task.WhenAll(task1, task2, task3);
Run Code Online (Sandbox Code Playgroud)

从方法内部,您需要token.ThrowIfCancellationRequested()在函数内部检查令牌并取消任务

public async Task Func1Async(CancellationToken token)
{
    foreach(var item in GetItems1())
    {
         await item.ProcessAsync(token);
         token.ThrowIfCancellationRequested();
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您可以通过制作扩展方法来稍微清理代码

public static class ExtensionMethods
{
    public Task CancelOnFaulted(this Task task, CancellationTokenSource cts)
    {
        task.ContinueWith(task => cts.Cancel(), cts.Token, taskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
        return task;
    }

    public Task<T> CancelOnFaulted<T>(this Task<T> task, CancellationTokenSource cts)
    {
        task.ContinueWith(task => cts.Cancel(), cts.Token, taskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
        return task;
    }
}
Run Code Online (Sandbox Code Playgroud)

这会使代码看起来像

CancellationTokenSource cts = new CancellationTokenSource();

var task1 = Func1Async(cts.Token).CancelOnFaulted(cts);
var task2 = Func2Async(cts.Token).CancelOnFaulted(cts);
var task3 = Func3Async(cts.Token).CancelOnFaulted(cts);

await Task.WhenAll(task1, task2, task3);
Run Code Online (Sandbox Code Playgroud)