简体   繁体   English

为什么 Thread.Sleep 有效而 Task.Delay 无效?

[英]Why does Thread.Sleep work but Task.Delay does not?

In my code I assume that outerFlag will be hit after innerFlag but it actually runs like fire and forget ( innerFlag is hit after outerFlag ).在我的代码中,我假设outerFlag将在innerFlag之后被击中,但它实际上innerFlag运行而忘记( innerFlagouterFlag之后被击中)。 When I use Thread.Sleep instead of Task.Delay flags are hit in correct order.当我使用Thread.Sleep而不是Task.Delay标志按正确顺序命中。

Here is the code:这是代码:

[Test]
public async Task Test() {

    bool innerFlag = false;
    bool outerFlag = false;

    await Lock(async () => {
        await Task.Delay(2000);
        innerFlag = true;
    });

    outerFlag = true;

    Thread.Sleep(1000);
    Thread.Sleep(2500);
}

private Task Lock(Action action) {
    return Task.Run(action);
}

I also noticed that when I call Task.Delay and set innerFlag without a Lock method but by direct lambda, it works as expected.我还注意到,当我调用Task.Delay并在没有Lock方法的情况下设置innerFlag ,但通过直接 lambda,它按预期工作。

Can somebody explain such behaviour?有人可以解释这种行为吗?

Your Lock method doesn't understand async delegates, so the async delegate you are trying to pass as argument is treated as async void .您的Lock方法不理解异步委托,因此您尝试作为参数传递的异步委托被视为async void Async voids are problematic in all sorts of ways and should be avoided , unless they are used for their intended purpose, as event handlers. Async voids 在各种方面都有问题, 应该避免,除非它们被用作其预期目的,作为事件处理程序。

To ensure that your method understand async delegates you must create an overload that accepts a Func<Task> as argument:为了确保您的方法理解异步委托,您必须创建一个接受Func<Task>作为参数的重载:

private Task Lock(Func<Task> func)
{
    return Task.Run(func);
}

Notice that the func argument can be passed directly to Task.Run , because this method understands async delegates too.请注意, func参数可以直接传递给Task.Run ,因为此方法也理解异步委托。 Not all built-in methods understand async delegates, with notable examples the Task.Factory.StartNew and Parallel.ForEach .并非所有内置方法都理解异步委托,值得注意的例子是Task.Factory.StartNewParallel.ForEach You must be cautious every time you add the async modifier in a delegate.每次在委托中添加async修饰符时都必须小心。 You must be sure that the called method understands async delegates, or else you may end up with async voids and the havoc they create.您必须确保被调用的方法理解异步委托,否则最终可能会出现异步无效和它们造成的破坏。

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

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