简体   繁体   English

Task.Delay(0)不是异步的

[英]Task.Delay(0) not asynchronous

I have the following code (yes, I could be simulating JavaScript setTimeout api) 我有以下代码(是的,我可以模拟JavaScript setTimeout api)

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

It looks like for timeout > 0 , the setTimeout works asynchronously wherein the control is returned back to the callee on await and callback is invoked after the task runs asynchronously. 看起来对于timeout > 0setTimeout异步工作,其中控件在await返回给callee ,并且在任务异步运行后调用callback BUT when timeout == 0 , the function behaves in a synchronous manner (code always run past the await line in the same thread without a context switch). 但是timeout == 0 ,该函数以同步方式运行(代码总是在没有上下文切换的同一线程中经过await行)。 On further digging, it turns out that Task.Delay is implemented to behave this way ( Task.Yield() versus Task.Delay(0) ) 在进一步挖掘时,事实证明Task.Delay实现为以这种方式运行( Task.Yield()与Task.Delay(0)

Wondering if there is a way to make Task.Delay(0) asynchronous or an alternate solution to make my setTimeout function asynchronous when timeout is 0 ? 想知道是否有办法使Task.Delay(0)异步或另一种解决方案使我的setTimeout函数在timeout0时异步? ( so that I could mimic JavaScript setTimeout functionality ) I see discussions on using Task.FromResult(true) or Task.WhenAll , but they don't seem to work. 这样我就可以模仿JavaScript setTimeout 功能 )我看到有关使用Task.FromResult(true)Task.WhenAll ,但它们似乎不起作用。

Indeed I can use Task.Delay(1) instead of Task.Delay(0) but it does not look organic. 事实上,我可以使用Task.Delay(1)而不是Task.Delay(0)但它看起来不是有机的。

The reason Task.Delay(0) does not run asynchronously is because the async-await state machine explicitly checks whether the task is completed and if it is, it runs synchronously. Task.Delay(0)不异步运行的原因是因为async-await状态机显式检查任务是否已完成,如果是,则它同步运行。

You can try using Task.Yield() , which will force the method to return immediately and resume the rest of the method on the current SynchornizationContext . 您可以尝试使用Task.Yield() ,它将强制该方法立即返回并在当前的SynchornizationContext上恢复该方法的其余部分。 eg: 例如:

async void setTimeout(dynamic callback, int timeout)
{
    if(timeout > 0)
    {
        await Task.Delay(timeout);
    }
    else
    { 
        await Task.Yield();
    }

    callback();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM