【问题标题】:What is the use-case for `CancellationTokenSource.TryReset`?`CancellationTokenSource.TryReset` 的用例是什么?
【发布时间】:2022-04-14 19:03:46
【问题描述】:
CancellationTokenSource 有一个 TryReset() 成员。 documentation 看起来如此严格,让我想知道它为什么存在。
- 只有在没有人调用过
Cancel() 时它才会起作用。
- 仅在使用其令牌发出的任何先前异步操作已完成时使用它才有效,这意味着(我认为)我需要挂在我的 Task 对象上以跟踪它是否仍在运行
- 当其他人试图取消操作时调用是不安全的,需要
那么,为什么人们会打扰TryReset?为什么不简单地为每个异步操作创建一个全新的CancellationTokenSource,然后在操作完成并且不再需要取消后将其丢弃? CancellationTokenSource 是一个非常昂贵的创建对象吗?
【问题讨论】:
标签:
c#
.net
task-parallel-library
cancellationtokensource
【解决方案1】:
让我在这里引用问题的背景和动机部分
当一个库或框架公开一个通常不会被取消的CancellationToken(例如HttpContext.RequestAborted)时,他们通常仍然需要在操作完成后处置支持CancellationTokenSource(CTS)而不是重用它以便为可能永远不会处理其注册的呼叫者提供帐户。
要使用RequestAborted 示例,Kestrel 在访问RequestAborted 令牌的每个请求之后处置支持CTS。如果 Kestrel 尝试为未来的请求重用支持 RequestAborted 令牌的 CTS 以减少分配,则可能会泄露任何未处理的注册并在无关请求中止时触发未处理的注册。
人们希望能够“重置”CTS 的另一种情况是在调用CancelAfter() 之后。这已经可以通过调用CancelAfter(Timeout.Infinite) 来实现,但这并不一定很明显,除非您阅读文档。在查看智能感知完成时,TryReset() 在这种情况下会立即有意义。
另一个好处是,如果重置失败,它会立即显而易见。如果您尝试使用CancelAfter() 重置超时,您必须在调用之后检查以验证它们在调用之前或期间没有取消导致CancelAfter() 无操作。这在第二个HttpClient 使用示例中得到了演示。