如何取消 CancellationToken

Posted

技术标签:

【中文标题】如何取消 CancellationToken【英文标题】:How to cancel a CancellationToken 【发布时间】:2015-09-01 17:25:31 【问题描述】:

我启动一个任务,然后启动其他任务等等。鉴于该树,如果任何任务失败,则整个操作的结果将毫无用处。我正在考虑使用取消令牌。令我惊讶的是,令牌没有“CancelThisToken()”方法...

我只有一个CancellationToken,如何取消它?

【问题讨论】:

您正在寻找 CancellationTokenSource msdn.microsoft.com/en-us/library/… @CoderDennis 我不明白如何获得仅给定令牌的令牌源... 如果您没有CancellationTokenSource,则无法取消它。令牌是所有线程共享的对象,该对象由CancellationTokenSource.Cancel() 方法设置。一旦这样做,CancellationToken.IsCancellationRequested 将是真的。在那之前,它永远都是假的。 (不能直接设置。)如果你没有CancellationTokenSource,那么没有什么可以抛出取消。你需要 CancellationTokenSource 来取消这样的线程。 【参考方案1】:

根据文档状态,您需要从源对象调用 cancel 方法。示例代码包含在您提供的链接中。以下是相关部分:

// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource();
previouslyProvidedToken = source.Token;
...
source.Cancel();

CancellationToken Struct

如果我只有一个 CancellationToken,我该如何取消它?

编辑:这是我几年前写的,现在重新审视它,我不知道它在写时或现在是否真的有效。保留原样以供后代使用。

如果不引用源,您将无法取消令牌。这并不意味着您需要首先生成令牌的CancellationTokenSource。当给定CancellationToken 时,您可以创建令牌源的新实例,将其令牌分配给提供的令牌,然后取消它。可以读取此令牌的所有其他方都将看到已请求取消它。

【讨论】:

@Leonardo,您应该首先创建令牌源,然后从中请求令牌。查看我提供的链接中的示例代码 这是我在工作中用于备份实用程序的方法 - 如果任何Task 失败,我的结果也将毫无用处。 (两个数据库,一个 SQL,一个 AS/400 DB2,不同步,这是不可接受的。所以如果出现任何故障,我会丢弃所有数据。) @Leonardo 如果只给出令牌,您无法获取源。 按照设计,当您拥有的只是该令牌时,您无法取消该令牌。如果可以的话,这将是一个破碎的系统。 @RyanS 我的意思是你应该将Servy的信息(或我的)添加到答案中。 在编辑中重写 previouslyProvidedToken 是一种不好的做法...如果提供的令牌的源被取消(在树中的更高级别),这在功能上不会对该取消做出反应.在这种情况下,传递 CancellationToken 完全没用,因此 Daniel Park 的回答提供了更好的解决方案。【参考方案2】:

作为迄今为止提供的答案的扩展,如果您希望为您的方法提供CancellationToken 实例,在内部取消,您应该检查CancellationTokenSource.CreateLinkedTokenSource。 本质上,这将在调用 cts.Cancel() 或其提供的令牌之一时取消。

【讨论】:

【参考方案3】:

令牌使您有权知道有人试图取消某事。它不赋予您实际发出取消信号的权利。只有取消令牌源才能为您提供。这是设计使然。

【讨论】:

也许直接解决问题?我认为答案是“你不能”(?)【参考方案4】:

CancellationTokenSource 实例生成CancellationToken 实例并在CTS 实例上调用Cancel

例如:Cancel()

还有一种方法可以优雅地取消线程而不触发异常。只需检查IsCancellationRequested 的 CT 并自行处理此案。

更多信息:Use of IsCancellationRequested property?

【讨论】:

那么当你被提供一个时,你就可以控制取消。您可以密切关注 IsCancellationRequested,也可以依靠框架在您的线程上抛出异常来强制执行此操作。

以上是关于如何取消 CancellationToken的主要内容,如果未能解决你的问题,请参考以下文章

取消 HttpClient 请求 - 为啥 TaskCanceledException.CancellationToken.IsCancellationRequested 为假?

C#源码生成器的cancellationtoken啥时候取消?

CancellationToken 取消机制

使用 CancellationToken 取消任务而不在任务中明确检查?

NamedPipeServerStream.ReadAsync() 在 CancellationToken 请求取消时不退出

CancellationToken 永远不会取消我长时间运行的加载数据功能