我有以下代码(是的,我可能在模拟JavaScript setTimeout
API)
async void setTimeout(dynamic callback, int timeout)
{
await Task.Delay(timeout);
callback();
}
看起来当timeout > 0
时,setTimeout
异步工作,控制权在await
时返回给callee
,并且callback
在任务异步运行后被调用。但是当timeout == 0
时,函数以同步方式运行(代码总是在同一线程中通过await
行执行而没有上下文切换)。进一步研究发现,Task.Delay
的实现方式就是这样的 (Task.Yield() versus Task.Delay(0))
想知道是否有办法使Task.Delay(0)
异步,或者有替代方案可以使我的 setTimeout
函数在timeout
为0
时异步?(这样我就可以模仿JavaScript的setTimeout
功能) 我看到有讨论使用 Task.FromResult(true)
或 Task.WhenAll
,但它们似乎不起作用。
确实可以使用Task.Delay(1)
代替
Task.Delay(0)
,但它看起来不自然。
Task.Yield
,它将把任务的继续处理方式交给TaskScheduler
来处理,这正如另一篇文章所演示的那样。如果你想强制使用一个新线程,可以使用Task.Delay(timeout).ConfigureAwait(false)
。 - Mike ZboraysetTimeout
本质上是将方法排队到引擎正在处理的队列的末尾(假设timeout=0
)。即使Delay
为0超时分派了一个线程,它也不会像JavaScript一样运行。 - RobTask.Delay(1)
的行为基本上与您从0期望的相同(因为它仍然小于最小时间量),并且执行将被调度回上下文(即对于WinForms/WPF,将被调度回UI线程)。 - Alexei LevenkovTask.Run
中(可能需要使用ConfigureAwait(false))。 - Mike Zboray