异步/等待取消机制

6

我有一个关于如何取消正在进行的异步操作的机制的问题,而不是在异步/等待上下文中使用取消令牌。我相信这是一项经过深入研究的设计决策,考虑到语言的命令式本质,但在实际情况中,必须将取消对象传递给所有异步方法,至少有点痛苦。C#社区中是否有其他设计思路,或者提出的取消机制是否仅仅可以?我觉得我可能遗漏了什么。


使用取消令牌的取消机制似乎是事情朝着的方向,包括在C# 5 CTP on Async中。http://msdn.microsoft.com/en-us/vstudio/gg316360。这不是叫做C# 5,但我在这里使用它来表示C#的“下一个”版本。 - Shiv Kumar
刚注意到你在问题中使用了“await”,所以你对CTP应该很熟悉。我认为任务并行库(.NET 4)证实了它提供的设施是正确的方法,因此异步CTP使用了相同的范例。 - Shiv Kumar
相关链接:http://stackoverflow.com/q/4914374/60761 - H H
@Henk Holterman:您提到的相关问题已经关闭。因此,我以更符合StackOverflow规范的方式提出了这个问题,并且只关注我认为最重要的点。 - Masterile
只是为了明确。问题涉及C# 5 vNext。 - Masterile
@master,只是一个记账的事情。请看右侧的“已链接”部分。这不是关闭投票。 - H H
2个回答

4
取消标记是最佳实践,特别适用于异步过程耗费资源、没有预设终止条件或涉及外部资源的情况。但是,如果您愿意,可以简单地“放弃”。而不是告诉异步线程中止处理并清理,只需“超时”;停止等待它完成,解除任何监听器,并继续运行。当线程最终完成时,它将检查其事件,意识到没有人在听,然后默默地终止。好处是简单性,但有许多情况下这将是一个坏事:
- 如果异步进程除非您告诉它停止,否则将永远保持运行状态,它将在后台持续运行,占用CPU和其他资源,直到应用程序关闭,此时线程将被终止。 - 如果异步线程正在执行可中止、可撤销的工作单元,例如DB操作,则如果用户按取消,他们期望已经完成的所有操作都已回滚。如果您停止监听并继续进行,则他们将得到他们认为已经取消的操作已完成的结果。 - 在大多数情况下,异步操作涉及需要花费时间处理的外部资源,还需要进行适当的清理。网络套接字必须断开连接,DB连接必须关闭,文件必须解锁等。虽然放弃意味着您不必处理这些,而是让线程正常结束,但常见的用户体验是用户感到厌烦,按取消然后重试操作。这意味着您在上一个异步操作中使用的资源必须被释放以再次使用它。

1
为了使异步操作的取消有意义,该操作必须执行离散步骤,因为操作需要检查取消令牌并停止自己继续执行。也就是说,取消令牌只是一种要实现的模式,而不是异步/等待的机制。
这意味着,如果您的异步操作只是一个带有完成句柄的I/O调用,那么您可能会放弃取消,因为在该调用返回之前,操作将无法检查您的令牌,此时没有任何收益。
因此,在考虑取消令牌时,首先要考虑是否可以通过支持取消来使该操作更有效,或者是否使用超时机制而不是等待它完成更有意义。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接