我在使用Task.WhenAll等待多重任务。当他们中的一个产生异常时,我想让Task.WhenAll(或等待多个任务的任何其他方式)立即取消其他任务并引发异常。如何取消并在Task.WhenAll引发异常时引发异常?
可能吗?
在此先感谢
我在使用Task.WhenAll等待多重任务。当他们中的一个产生异常时,我想让Task.WhenAll(或等待多个任务的任何其他方式)立即取消其他任务并引发异常。如何取消并在Task.WhenAll引发异常时引发异常?
可能吗?
在此先感谢
Cancellation is coopertive的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);
从方法里面,你会需要把token.ThrowIfCancellationRequested()
的功能里面,以检查令牌和取消任务
public async Task Func1Async(CancellationToken token)
{
foreach(var item in GetItems1())
{
await item.ProcessAsync(token);
token.ThrowIfCancellationRequested();
}
}
注意:您可以通过使清理代码位扩展方法
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;
}
}
这会使代码看起来像
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);
OP询问'WhenAll'而不是'WaitAll'。 –
@DavidPine这是第一句话中的拼写错误,如果你看看它使用WhenAll的代码示例。 –
我尽可能多地假设,不想编辑你的答案,但不知道这是否是有意的。 –
你能检查答案吗? http://stackoverflow.com/questions/27238232/how-can-i-cancel-task-whenall –
这不是WhenAll工作的方式。你可能需要重新考虑你的方法。 –
@EvertonSantos感谢您的链接!但我的情况不同,我需要注意异常情况。如果任务中出现异常,我需要取消所有任务 –