Task.Delay(0)不是异步的

时间:2015-10-29 06:03:48

标签: c# multithreading asynchronous async-await

我有以下代码(是的,我可以模拟JavaScript setTimeout api)

    async void setTimeout(dynamic callback, int timeout)
    {
        await Task.Delay(timeout);
        callback();
    }

对于timeout > 0setTimeout异步工作,其中控件返回callee上的awaitcallback之后调用timeout == 0任务以异步方式运行。 但是Task.Delay时,该函数以同步方式运行(代码总是在没有上下文切换的同一线程中经过await行)。在进一步挖掘时,事实证明setTimeout实现了这种方式(Task.Yield() versus Task.Delay(0)

想知道是否有办法使Task.Delay(0)异步,或者在timeout0时使setTimeout函数异步? (以便我可以模仿JavaScript Task.FromResult(true) 功能)我看到有关使用Task.WhenAllTask.Delay(1)的讨论,但他们没有似乎工作。

确实,我可以使用Task.Delay(0)代替ShowDialog(),但它看起来不是有机的。

1 个答案:

答案 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();
}