异步/等待取消机制

问题描述:

我有一个问题,可以使用什么机制来取消正在进行的异步操作,而不是异步/等待上下文中的取消令牌。我确信这是一个考虑到语言的命令性质的充分研究的设计决定,但在实际情况下,必须将取消对象传递给所有异步方法,至少有点痛苦。还有另一个来自C#社区的设计思路,或者建议的取消机制是否正确?我想我错过了一些东西。异步/等待取消机制

+0

使用取消令牌的取消机制似乎是事情发展的方向,包括在C#5的异步CTP中。 http://msdn.microsoft.com/en-us/vstudio/gg316360。这不是叫C#5,但我在这里用它来表示C#的“下一个”版本。 – 2011-02-07 21:29:31

取消令牌是最佳实践,尤其是当异步过程昂贵,没有预设结束条件或涉及外部资源时。

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

  • 如果除非你告诉它停止异步进程将继续处理永远,它会继续在后台运行,搭售启动CPU和其他资源,直到应用程序关闭,此时线程将被终止。
  • 如果异步线程正在执行一个可中止的,可逆的工作单元,例如数据库操作,如果用户按下取消,他们预期到目前为止所做的任何事情都已被回滚。如果你停止倾听并继续前进,他们会得到的是他们认为他们取消了的事情。
  • 在大多数情况下,异步操作涉及需要时间处理的外部资源,并且还需要进行适当的清理。网络套接字必须断开连接,数据库连接关闭,文件解锁等。尽管放弃意味着你不必处理这些事情,而是让线程正常结束,但普通的用户体验是让用户感到厌烦,打取消然后重试该操作。这意味着您在之前的异步操作中使用的资源必须发布才能再次使用它。

为了异步操作的取消是有道理的,该操作必须执行谨慎的步骤,因为它是由操作检查取消标记和持续自行停止。即取消标记仅仅是要实现的模式而不是异步/等待的机制。

这意味着如果你的异步操作只是一个带有完成句柄的I/O调用,那么你可以放弃而不是取消,因为操作不会有oppurtunity来检查你的令牌直到那个电话回来了,没有什么可以获得的。因此,当考虑取消令牌时,首先考虑是否可以通过支持取消或者是否只是不等待它完成(即使用超时机制)来更有效地进行该操作。