Task.Delay(0)不是异步的

inf*_*ity 9 c# multithreading asynchronous async-await

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

    async void setTimeout(dynamic callback, int timeout)
    {
        await Task.Delay(timeout);
        callback();
    }
Run Code Online (Sandbox Code Playgroud)

它看起来像timeout > 0,在setTimeout异步其中,控制返回到作品calleeawait,并callback在任务完成后调用异步运行.但是,timeout == 0函数以同步方式运行时(代码总是在没有上下文切换的同一线程中经过await行).在进一步挖掘时,事实证明这Task.Delay是以这种方式实现的(Task.Yield()与Task.Delay(0))

不知道是否有一种方法,使Task.Delay(0)或异步的替代解决方案,使我的setTimeout功能异步时timeout0?(这样我可以模仿JavaScript setTimeout 功能)我看到有关使用Task.FromResult(true)或的讨论Task.WhenAll,但它们似乎不起作用.

事实上,我可以使用Task.Delay(1)Task.Delay(0)不是看起来有机.

Ned*_*nov 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();
}
Run Code Online (Sandbox Code Playgroud)

  • 这有一个竞争条件,如果`timeout`非常低,仍可能导致同步行为.我建议使用`await Task.Yield(); 等待Task.Delay(超时);`. (3认同)
  • @Aron 他一直用 javascript :) (3认同)
  • 为什么回调不是`Action`? (2认同)