Jac*_*cob 5 c# multithreading multitasking task-parallel-library
我有一个具有相同CancellationTokenSource.
我希望当前线程等待所有任务完成或任务被取消。
Task.WaitAll(tasks.ToArray(), searchCencellationTokenSource.Token);
System.Console.WriteLine("Done !");
Run Code Online (Sandbox Code Playgroud)
即使当前线程处于等待状态,这些任务也可能被另一个任务取消。这是正常行为。
然而,当当前线程处于等待状态并且另一个任务取消任务时,WaitAll 抛出CancellationTokenSource一条消息:“操作被取消。”。
我知道它被取消了,我是故意这样做的。我只是希望它在任务取消或完成后继续执行下一个代码,而不抛出异常。
我知道我可以用 try & catch 来包装这段代码,但是抛出异常是一个繁重的操作,我不希望它发生在这样的正常行为上。
这种阻塞机制可以改写为:
Task.WhenAll(taskA, taskB, taskC).Wait()
Run Code Online (Sandbox Code Playgroud)
这为您提供了一个我们可以等待但也可以管理取消的任务。因此,要忽略取消异常,您可以执行以下操作:
Task.WhenAll(taskA, taskB, taskC).ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled).Wait();
Run Code Online (Sandbox Code Playgroud)
这不会抛出OperationCancelledException.
然后可以将其包装到扩展方法中,如下所示:
public static class TaskExtensions
{
public static Task IgnoreCancellation(this Task task)
{
return task.ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled);
}
}
Run Code Online (Sandbox Code Playgroud)
这将允许您再次编写以下内容而不会遇到OperationCancelledException:
Task.WhenAll(taskA, taskB, taskC).IgnoreCancellation().Wait();
Run Code Online (Sandbox Code Playgroud)
这是一个测试装置,显示了该方法的工作原理:
public class IgnoreTaskCancellation
{
[Fact]
public void ShouldThrowAnAggregateException()
{
CancellationTokenSource cts = new CancellationTokenSource(10);
Task taskA = Task.Delay(20, cts.Token);
Task taskB = Task.Delay(20, cts.Token);
Task taskC = Task.Delay(20, cts.Token);
Assert.Throws<AggregateException>(() => Task.WhenAll(taskA, taskB, taskC).Wait());
}
[Fact]
public void ShouldNotThrowAnException()
{
CancellationTokenSource cts = new CancellationTokenSource(10);
Task taskA = Task.Delay(20, cts.Token);
Task taskB = Task.Delay(20, cts.Token);
Task taskC = Task.Delay(20, cts.Token);
Task.WhenAll(taskA, taskB, taskC).ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled).Wait();
}
[Fact]
public void ShouldNotThrowAnExceptionUsingIgnore()
{
CancellationTokenSource cts = new CancellationTokenSource(10);
Task taskA = Task.Delay(20, cts.Token);
Task taskB = Task.Delay(20, cts.Token);
Task taskC = Task.Delay(20, cts.Token);
Task.WhenAll(taskA, taskB, taskC).IgnoreCancellation().Wait();
}
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。
| 归档时间: |
|
| 查看次数: |
2297 次 |
| 最近记录: |