等待任务超时

编程入门 行业动态 更新时间:2024-10-23 23:28:52
本文介绍了等待任务超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试编写一个帮助程序方法,该方法允许我传递任意任务和超时.如果任务在超时之前完成,则调用成功委托,否则调用错误委托.该方法如下所示:

I'm trying to write a helper method which allows me to pass in an arbitrary task and a timeout. If the task completes before the timeout, a success delegate is called, otherwise an error delegate is called. The method looks like this:

public static async Task AwaitWithTimeout(Task task, int timeout, Action success, Action error) { if (await Task.WhenAny(task, Task.Delay(timeout)) == task) { if (success != null) { success(); } } else { if (error != null) { error(); } } }

现在这个似乎大部分时间都可以工作,但是我也想编写一些测试来确保.令我惊讶的是,该测试失败了,并调用了错误委托而不是成功:

Now this seems to work most of the time, but i wanted to write some tests as well to make sure. This test, to my surprise fails, and calls the error delegate instead of the success:

var taskToAwait = Task.Delay(1); var successCalled = false; await TaskHelper.AwaitWithTimeout(taskToAwait, 10, () => successCalled = true, null); Assert.IsTrue(successCalled);

但是,此测试是绿色的:

This test, however, is green:

var taskToAwait = Task.Run(async () => { await Task.Delay(1); }); var successCalled = false; await TaskHelper.AwaitWithTimeout(taskToAwait, 10, () => successCalled = true, null); Assert.IsTrue(successCalled);

我如何使两个测试都变为绿色?我对Task.WhenAny的用法不正确吗?

How do i make both tests green? Is my usage of Task.WhenAny incorrect?

推荐答案

计时器不准确.默认情况下,它们的精度约为15毫秒.低于此值的任何时间都将在15ms的间隔内触发. 参阅相关答案.

Timers are inaccurate. By default their accuracy is around 15 ms. Anything lower than that will trigger in 15ms interval. Refer related answer.

假设您有1毫秒计时器和10毫秒计时器;两者大致相等,所以您在那里得到的结果不一致.

Given that you have 1ms timer and 10ms timer; both are roughly equal so you get inconsistent results there.

包装在Task.Run中并声称可以正常工作的代码只是一个巧合.当我尝试几次时,结果不一致.有时由于提到的相同原因而失败.

The code you wrapped in Task.Run and claims to be working is just a coincidence. When I tried several times, results are inconsistent. It fails sometimes for the same reason mentioned.

最好增加超时时间,或者只传递已经完成的任务.

You're better off increasing the timeout or just pass in a already completed task.

例如,以下测试应始终通过.请记住,您的测试应该一致而不易碎.

For example following test should consistently pass. Remember that your test should be consistent not brittle.

[Test] public async Task AwaitWithTimeout_Calls_SuccessDelegate_On_Success() { var taskToAwait = Task.FromResult(0); var successCalled = false; await TaskHelper.AwaitWithTimeout(taskToAwait, 10, () => successCalled = true, ()=>{ }); Assert.IsTrue(successCalled); }

对于永无止境的任务,请使用TaskCompletionSource并且不要设置其结果.

For never ending task use TaskCompletionSource and don't set its result.

[Test] public async Task AwaitWithTimeout_Calls_ErrorDelegate_On_NeverEndingTask() { var taskToAwait = new TaskCompletionSource<object>().Task; var errorCalled = false; await TaskHelper.AwaitWithTimeout(taskToAwait, 10, () => { }, ()=> errorCalled = true); Assert.IsTrue(errorCalled); }

此外,我建议您避免使用null.您可以只将空的委托作为参数传递.然后,您就不想在整个代码库中散布null检查.

Also I recommend you to avoid using null. You can just pass the empty delegate as a parameter. Then you don't want to have null checks scattered all over your codebase.

我将辅助方法编写为:

public static async Task AwaitWithTimeout(this Task task, int timeout, Action success, Action error) { if (await Task.WhenAny(task, Task.Delay(timeout)) == task) { success(); } else { error(); } }

请注意,上述方法是扩展方法;因此您可以使用任务实例来调用它.

Note that above method is an extension method; so you can call it with task instance.

await taskToAwait.AwaitWithTimeout(10, () => { }, ()=> errorCalled = true);//No nulls, just empty delegate

更多推荐

等待任务超时

本文发布于:2023-11-05 12:35:57,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1560862.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!