如何在不抛出TaskCanceledExceptions的情况下等待任务?

Joe*_*ite 23 exception-handling task-parallel-library cancellation

我有一个创建一些任务的方法,然后在返回之前用WaitAll等待它们.问题是,如果这些任务被取消,那么WaitAll会抛出一个包含大量TaskCanceledExceptionAggregateException.

这意味着WaitAll将在两种不同的情况下抛出异常:

  • 表示真正错误的例外情况.这意味着我们不知道如何处理这种情况; 它们需要作为未处理的异常进行传播,直到它们最终终止进程.
  • 表示用户单击"取消"按钮的例外情况.这意味着任务被取消并清理,程序应继续正常运行.

后者完全符合一个令人烦恼的例外的定义:它是一个完全非特殊情况下抛出的异常,所以我必须抓住它才能恢复正常的控制流程.幸运的是,它很容易捕获,对吧?只需添加catch (AggregateException)- 哦等等,这是在发生致命错误时被抛出的相同类型.

我需要在返回之前等待任务完成运行(我需要知道他们不再使用他们的数据库连接,文件句柄或其他任何东西),所以我确实需要WaitAll或类似的东西.如果任何任务出现故障,我确实希望这些异常作为未处理的异常传播.我只是不想要取消的例外.

如何防止WaitAll为已取消的任务抛出异常?

Joã*_*elo 28

AggregateException提供了一个Handle可用于这些情况的方法.例如,如果你想忽略,TaskCanceledException你可以这样做:

var all = new AggregateException(
    new NullReferenceException(),
    new TaskCanceledException(),
    new TaskCanceledException(),
    new InvalidOperationException(),
    new TaskCanceledException());

try
{
    throw all;
}
catch (AggregateException errors)
{
    errors.Handle(e => e is TaskCanceledException);
} 
Run Code Online (Sandbox Code Playgroud)

如果所有异常都是类型TaskCanceledException,则该Handle方法不会抛出任何异常; 否则AggregateException将抛出仅包含未处理异常的new .