我正在使用 Task.WhenAll 等待多项任务。当其中一个生成异常时,我希望 Task.WhenAll(或等待多个任务的任何其他方式)立即取消其他任务并引发异常。
这可能吗?
提前致谢
最佳答案
Cancellation is coopertive WhenAll
无法取消线程,但您可以向所有线程传递一个 CancellationToken
并在遇到异常时触发 token 。
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);
在方法内部,您需要将 token.ThrowIfCancellationRequested()
放入函数内部以检查 token 并取消任务
public async Task Func1Async(CancellationToken token)
{
foreach(var item in GetItems1())
{
await item.ProcessAsync(token);
token.ThrowIfCancellationRequested();
}
}
注意:您可以通过制作扩展方法来清理代码
public static class ExtensionMethods
{
public static Task CancelOnFaulted(this Task task, CancellationTokenSource cts)
{
task.ContinueWith(task => cts.Cancel(), cts.Token, taskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
return task;
}
public static Task<T> CancelOnFaulted<T>(this Task<T> task, CancellationTokenSource cts)
{
task.ContinueWith(task => cts.Cancel(), cts.Token, taskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
return task;
}
}
这会让代码看起来像
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);
关于c# - 如果引发任何异常,如何在 Task.WhenAll 上取消并引发异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41899842/