gpt4 book ai didi

C# 任务忽略取消超时

转载 作者:行者123 更新时间:2023-11-30 19:38:55 25 4
gpt4 key购买 nike

我正在尝试为任意代码编写一个包装器,它将在给定的超时期限后取消(或至少停止等待)代码。

我有以下测试和实现

[Test]
public void Policy_TimeoutExpires_DoStuff_TaskShouldNotContinue()
{
var cts = new CancellationTokenSource();
var fakeService = new Mock<IFakeService>();
IExecutionPolicy policy = new TimeoutPolicy(new ExecutionTimeout(20), new DefaultExecutionPolicy());
Assert.Throws<TimeoutException>(async () => await policy.ExecuteAsync(() => DoStuff(3000, fakeService.Object), cts.Token));

fakeService.Verify(f=>f.DoStuff(),Times.Never);
}

和“DoStuff”方法

private static async Task DoStuff(int sleepTime, IFakeService fakeService)
{

await Task.Delay(sleepTime).ConfigureAwait(false);
var result = await Task.FromResult("bob");
var test = result + "test";
fakeService.DoStuff();
}

以及IExecutionPolicy.ExecuteAsync的实现

public async Task ExecuteAsync(Action action, CancellationToken token)
{
var cts = new CancellationTokenSource();//TODO: resolve ignoring the token we were given!

var task = _decoratedPolicy.ExecuteAsync(action, cts.Token);
cts.CancelAfter(_timeout);

try
{
await task.ConfigureAwait(false);
}
catch(OperationCanceledException err)
{
throw new TimeoutException("The task did not complete within the TimeoutExecutionPolicy window of" + _timeout + "ms", err);
}
}

应该发生的是测试方法尝试花费 >3000 毫秒,超时应该发生在 20 毫秒,但这并没有发生。为什么我的代码没有按预期超时?

编辑:

按要求——decoratedPolicy如下

public async Task ExecuteAsync(Action action, CancellationToken token)
{
token.ThrowIfCancellationRequested();
await Task.Factory.StartNew(action.Invoke, token);
}

最佳答案

如果我理解正确,您正试图为不支持超时/取消的方法支持超时。

通常这是通过启动具有所需超时值的计时器来完成的。如果计时器先触发,那么您可以抛出异常。使用 TPL,您可以使用 Task.Delay(_timeout) 而不是计时器。

public async Task ExecuteAsync(Action action, CancellationToken token)
{
var task = _decoratedPolicy.ExecuteAsync(action, token);

var completed = await Task.WhenAny(task, Task.Delay(_timeout));
if (completed != task)
{
throw new TimeoutException("The task did not complete within the TimeoutExecutionPolicy window of" + _timeout + "ms");
}
}

注意:这不会停止 _decoratedPolicy.ExecuteAsync 方法的执行,而是会忽略它。

如果您的方法确实支持取消(但不及时),那么最好在超时后取消任务。您可以通过创建链接 token 来实现。

public async Task ExecuteAsync(Action action, CancellationToken token)
{
using(var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token))
{
var task = _decoratedPolicy.ExecuteAsync(action, linkedTokenSource.Token);

var completed = await Task.WhenAny(task, Task.Delay(_timeout));
if (completed != task)
{
linkedTokenSource.Cancel();//Try to cancel the method
throw new TimeoutException("The task did not complete within the TimeoutExecutionPolicy window of" + _timeout + "ms");
}
}
}

关于C# 任务忽略取消超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30351553/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com