为什么Thread.Sleep可以工作,但Task.Delay不能工作?

时间:2020-01-29 13:13:36

标签: c# .net asynchronous async-await task

在我的代码中,我假设outerFlag之后会被innerFlag击中,但实际上它就像是一发不可收拾({{1}之后被innerFlag被击中)。当我使用outerFlag而不是Thread.Sleep时,会以正确的顺序命中标志。

代码如下:

Task.Delay

我还注意到,当我调用[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); } 并设置Task.Delay而不使用innerFlag方法但通过直接lambda设置时,它可以按预期工作。

有人可以解释这种行为吗?

1 个答案:

答案 0 :(得分:1)

您的Lock方法不理解异步委托,因此您尝试作为参数传递的异步委托被视为async void。异步空缺在各种方面都存在问题,should be avoided除非有预定用途,否则它们都是事件处理程序。

为确保您的方法理解异步委托,您必须创建一个接受Func<Task>作为参数的重载:

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

请注意,func参数可以直接传递给Task.Run,因为此方法也可以理解异步委托。并非所有内置方法都可以理解异步委托,其中包括著名的示例Task.Factory.StartNewParallel.ForEach。每次在委托中添加async修饰符时都必须谨慎。您必须确保被调用的方法能够理解异步委托,否则可能会导致异步空缺和它们造成的破坏。