异步/等待取消机制

时间:2011-02-07 21:04:14

标签: c# async-await

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

2 个答案:

答案 0 :(得分:4)

取消令牌是最佳做法,特别是当异步过程很昂贵,没有预设的结束条件或涉及外部资源时。

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

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

答案 1 :(得分:1)

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

这意味着如果你的异步操作只是一个带有完成句柄的I / O调用,你也可以放弃而不是取消,因为操作不会有机会检查你的令牌,直到那个电话回来了,没有什么可以获得的。

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