Task.WhenAllを使用して複数のタスクを待っています。それらの1つが例外を生成した場合、Task.WhenAll(または複数のタスクを待機する他の方法)で他のタスクをすぐにキャンセルして例外を発生させたいと思います。
出来ますか?
前もって感謝します
キャンセルは協調的であり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);
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加