【问题标题】:async/await cancellation mechanismasync/await 取消机制
【发布时间】:2011-02-07 21:04:14
【问题描述】:

我有一个问题,即可以使用什么机制来取消正在进行的异步操作,而不是使用 async/await 上下文中的取消令牌。我确信这是一个经过充分研究的设计决策,它考虑了语言的命令性质,但在实际情况下,必须将取消对象传递给所有异步方法,至少有点痛苦。 c#社区还有另一种设计思路,还是提议的取消机制就好了?我想我错过了什么。

【问题讨论】:

  • 使用取消令牌的取消机制似乎是事情的发展方向,包括在 C# 5 CTP on Async 中。 msdn.microsoft.com/en-us/vstudio/gg316360 。它不叫 C# 5,但我在这里用它来表示 C# 的“下一个”版本。
  • 刚刚注意到您在问题中使用了“等待”,因此您熟悉 CTP。我认为 Task Parallel Library (.NET 4) 有点确认它提供的设施是可行的方法,因此 Async CTP 使用相同的范例。
  • @Henk Holterman:您提到的相关问题已关闭。出于这个原因,我以一种对 StackOverflow 更友好的方式编写了这个问题。并且只关注我认为更重要的点。
  • 只是为了清楚。这个问题与 C# 5 vNext 有关。

标签: c# async-await


【解决方案1】:

取消令牌是最佳实践,尤其是在异步进程成本高、没有预设结束条件或涉及外部资源时。

但是,如果您愿意,您可以简单地“放弃”。而不是告诉异步线程中止处理和清理,只是“超时”;停止等待它完成,分离任何侦听器,然后继续运行。当线程最终完成时,它会检查它的事件,发现没有人在听,然后静默终止。好处是简单,但是在很多情况下这将是一件坏事:

  • 如果异步进程将一直持续处理,除非您告诉它停止,否则它将继续在后台运行,占用 CPU 和其他资源,直到应用程序关闭,此时线程将被终止。李>
  • 如果异步线程正在执行可中止、可逆的工作单元(例如 DB 操作),如果用户按下取消,他们预计到目前为止所做的任何事情都已回滚。如果您停止倾听并继续前进,他们将得到的是他们认为他们取消的内容已被执行。
  • 在大多数情况下,异步操作涉及需要时间处理的外部资源,并且还需要适当的清理。网络套接字必须断开,数据库连接关闭,文件解锁等。虽然放弃意味着你不必处理这些,而是​​让线程正常结束,一个常见的用户体验是用户厌倦,命中取消,然后重试该操作。这意味着您在之前的异步操作中使用的资源必须被释放才能再次使用它。

【讨论】:

    【解决方案2】:

    为了使异步操作的取消有意义,该操作必须执行谨慎的步骤,因为该操作需要检查取消令牌并停止自身继续。 IE。取消令牌只是一种要实现的模式,而不是异步/等待机制。

    这意味着如果您的异步操作只是一个带有完成句柄的 I/O 调用,您不妨放弃而不是取消,因为在此之前操作将没有机会检查您的令牌调用返回,此时没有任何收获。

    因此,在考虑取消令牌时,首先要考虑是否可以通过支持取消来提高此操作的效率,或者不等待它完成(即使用超时机制)是否更有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-03
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      相关资源
      最近更新 更多