当前位置:  开发笔记 > 编程语言 > 正文

TaskCancellationException如何避免成功控制流程中的异常?

如何解决《TaskCancellationException如何避免成功控制流程中的异常?》经验,为你挑选了1个好方法。

在我们的应用程序中,我们使用async/await和Tasks工作了很多.因此它确实使用Task.Run很多,有时使用内置的取消支持CancellationToken.

public Task DoSomethingAsync(CancellationToken cancellationToken)
{
    return Task.Run(() =>
    {
        while (true)
        {
            if (cancellationToken.IsCancellationRequested) break;
            //do some work
        }
    }, cancellationToken);
}

如果我现在使用CancellationToken取消执行,则执行会在下一个循环开始时停止,或者如果Task根本没有启动,则会抛出异常(Task.Run中的TaskCanceledException).现在的问题是为什么Task.Run使用Exception控制成功取消而不是仅返回已完成的Task.是否有任何具体原因MS没有坚持"不要使用例外来控制执行流程"规则?

如何在一个完全无用的try catch(TaskCancelledException)块中避免使用Boxing支持取消(这很多)的每个方法?



1> Luaan..:

好吧,你不能真正看到你的非常简单的情况 - 你实际上并没有使用结果Task,你不需要通过复杂的调用堆栈传播取消.

首先,您Task可能会返回一个值.操作取消后您返回什么?

其次,可能还有其他任务跟随您取消的任务.您可能希望在方便时通过其他任务传播取消.

例外传播.任务取消与Thread.Abort此用法完全相同- 当您发出a时Thread.Abort,a ThreadAbortException用于确保您一直放松到顶部.否则,你的所有方法都必须检查他们调用的每个方法的结果,检查它们是否被取消,并在需要时自行返回 - 我们已经看到人们将忽略老派C中的错误返回值:)

最后,任务取消,就像线程中止一样,是一种特殊情况.它已经涉及同步,堆栈展开等.

但是,这并不意味着您必须使用try-catch捕获异常 - 您可以使用任务状态.例如,您可以使用这样的辅助函数:

public static Task DefaultIfCanceled(this Task @this, T defaultValue = default(T))
{
  return
    @this.ContinueWith
      (
        t =>
        {
          if (t.IsCanceled) return defaultValue;

          return t.Result;
        }
      );
}

你可以用作哪个

await SomeAsync().DefaultIfCanceled();

当然,应该注意的是,noöne强迫您使用这种取消方法 - 它只是为了方便而提供.例如,您可以使用自己的放大类型来保留取消信息,并手动处理取消.但是当你开始这样做时,你会发现使用异常处理取消的原因 - 在命令式代码中执行此操作是一件痛苦的事情,所以你要么浪费了很多精力才能获得收益,要么你将转向更实用的编程方式(来吧,我们有cookies!*).

(*)免责声明:我们实际上没有cookies.但你可以自己做!

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有