[英]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
运行而忘记( innerFlag
在outerFlag
之后被击中)。 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.StartNew
和Parallel.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.