我使用一个传递的取消令牌,以便可以干净地关闭我的服务。服务具有不断尝试连接到其他服务的逻辑,因此令牌是打破这些在单独线程中运行的重试循环的好方法。我的问题是,我需要调用一个服务,该服务具有内部重试逻辑,但如果重试失败,则在一段时间后返回。我想创建一个新的取消令牌与超时,这将为我做这一点。这样做的问题是,我的新令牌没有链接到“master”令牌,所以当master令牌被取消时,我的新令牌仍然是活动的,直到它超时或建立连接并返回。我想做的是将两个令牌链接在一起,这样当主令牌被取消时,我的新令牌也将取消。我尝试使用CancellationTokenSource.CreateLinkedTokenSource
方法,但当我的新令牌超时时,它也取消了主令牌。是否有一种方法可以完成我需要对令牌进行的操作,或者它需要更改重试逻辑(可能不太容易做到这一点)
这就是我想要做的:
主令牌-传递各种功能,以便服务可以干净地关闭。临时令牌-传递给单个函数并设置为一分钟后超时
如果主令牌被取消,则临时令牌也必须被取消。
当临时令牌到期时,不得取消主令牌。
4条答案
按热度按时间vmjh9lq91#
你想使用
CancellationTokenSource.CreateLinkedTokenSource
。它允许您为“子”CancellationTokenSource
创建“父”CancellationToken
。下面是一个简单的例子:
输出符合预期:
取消子CTS
子CTS:真
父CTS:假
取消父CTS
子CTS:真
父CTS:真
des4xlb02#
如果您只有
CancellationToken
,而不是CancellationTokenSource
,则仍然可以创建链接的取消令牌。你可以简单地使用Register
方法来触发the(pseudo)child的取消:您可以使用
CancellationTokenSource
执行通常要执行的任何操作。例如,您可以在一段时间后取消它,甚至覆盖您以前的令牌。2mbi3lxu3#
作为i3arnon already answered,您可以使用
CancellationTokenSource.CreateLinkedTokenSource()
完成此操作。我想尝试展示一种模式,当您想要区分取消整个任务和取消子任务而不取消整个任务时,如何使用这样的标记。当临时令牌到期时,不得取消主令牌。
请注意,
MyAsyncTask()
的签名接受CancellationToken
而不是CancellationTokenSource
。由于该方法只能访问CancellationToken
上的成员,因此它不会意外取消主/父令牌。我建议您以这样一种方式组织代码,即主任务的CancellationTokenSource
对尽可能少的代码可见。在大多数情况下,这可以通过将CancellationTokenSource.Token
传递给方法来完成,而不是共享对CancellationTokenSource
的引用。CancellationToken
,而无需访问其CancellationTokenSource
。希望这是不可能的,但如果可能的话,这将被认为是不好的做法,一般来说是不值得担心的。flmtquvp4#
有几个答案提到了从父令牌创建链接令牌源。如果从其他地方传递了子标记,则此模式将失效。相反,您可能希望从主令牌和传递给方法的令牌创建链接令牌源。
从Microsoft的文档中:https://learn.microsoft.com/en-us/dotnet/standard/threading/how-to-listen-for-multiple-cancellation-requests
通常在向方法传递令牌时,您只能访问取消令牌。要使用其他答案的方法,您可能必须重新传输所有其他方法以传递令牌源。此方法允许您仅使用令牌。