使用取消令牌为用户定义的函数设置超时
Posted
技术标签:
【中文标题】使用取消令牌为用户定义的函数设置超时【英文标题】:Set timeout for user defined function using cancelation token 【发布时间】:2020-10-27 23:36:56 【问题描述】:如果任务持续时间超过 3 秒,我想取消它。
第一次尝试:
public static async Task DoSomething()
await Task.Delay(10000);
var task1 = DoSomething();
var task2 = Task.Delay(3000);
Task.WaitAny(task1, task2);
第二次尝试:
我尝试使用cancellationToken
,但它似乎不起作用。它等待函数 10 秒,它似乎忽略了 3 秒延迟取消。
var cts = new CancellationTokenSource();
var token = cts.Token;
cts.CancelAfter(TimeSpan.FromSeconds(3));
await Task.Run(async () => await DoSomething(), token);
有人可以帮助我使用cancellationToken
实现此类功能吗?
【问题讨论】:
在 .NET is cooperative 中取消。如果它支持取消,您可以取消某些东西,否则,您不能。您可以取消等待操作,就像您在示例中所做的那样,但不能取消操作本身。 哦,原来如此,谢谢你的回答,所以我只能使用取消令牌如果函数本身支持它 是的,Tigran,没错。也恭喜你战胜了 Mikhail Botvinnik! ?????? 【参考方案1】:您需要将CancellationToken
传递给DoSomething
并在那里使用它:
public static async Task DoSomething(CancellationToken t)
await Task.Delay(10000, t);
var cts = new CancellationTokenSource();
var token = cts.Token;
cts.CancelAfter(TimeSpan.FromSeconds(3));
try
await Task.Run(async () => await DoSomething(token), token);
catch (OperationCanceledException ex)
// canceled
来自docs:
当任务实例观察到用户代码抛出的 OperationCanceledException 时,它会将异常的标记与其关联的标记(传递给创建任务的 API 的标记)进行比较。如果它们相同并且令牌的 IsCancellationRequested 属性返回 true,则任务将此解释为确认取消并转换到 Canceled 状态。如果您不使用 Wait 或 WaitAll 方法来等待任务,则任务只是将其状态设置为 Canceled。
但似乎Task
转换为Canceled
与是否提供相同的令牌无关。
我发现将令牌传递给Task.Run
与否之间的唯一区别是,如果在任务开始执行之前请求取消,则任务不会执行,而是设置为Canceled
状态并抛出一个@ 987654329@ 异常。
【讨论】:
感谢您的回答,但这不是我想要的。您正在调用本机具有参数取消令牌的函数 task.delay,如果函数正在执行一些不支持取消令牌的操作 哦,Theodor Zoulias 已经回答了我的问题以上是关于使用取消令牌为用户定义的函数设置超时的主要内容,如果未能解决你的问题,请参考以下文章
Polly Timeout 乐观使用 HttpClientFactory。如何使用取消令牌?