我有以下代码(是的,我可以模拟JavaScript setTimeout
api)
async void setTimeout(dynamic callback, int timeout)
{
await Task.Delay(timeout);
callback();
}
对于timeout > 0
,setTimeout
异步工作,其中控件返回callee
上的await
,callback
之后调用timeout == 0
任务以异步方式运行。 但是当Task.Delay
时,该函数以同步方式运行(代码总是在没有上下文切换的同一线程中经过await行)。在进一步挖掘时,事实证明setTimeout
实现了这种方式(Task.Yield() versus Task.Delay(0))
想知道是否有办法使Task.Delay(0)异步,或者在timeout
为0
时使setTimeout
函数异步? (以便我可以模仿JavaScript Task.FromResult(true)
功能)我看到有关使用Task.WhenAll
或Task.Delay(1)
的讨论,但他们没有似乎工作。
确实,我可以使用Task.Delay(0)
代替ShowDialog()
,但它看起来不是有机的。
答案 0 :(得分:13)
Task.Delay(0)
不异步运行的原因是因为async-await状态机显式检查任务是否已完成,如果是,则它同步运行。
您可以尝试使用Task.Yield(),这会强制该方法立即返回,并在当前SynchornizationContext
上恢复该方法的其余部分。例如:
async void setTimeout(dynamic callback, int timeout)
{
if(timeout > 0)
{
await Task.Delay(timeout);
}
else
{
await Task.Yield();
}
callback();
}