在我的代码中,我假设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设置时,它可以按预期工作。
有人可以解释这种行为吗?
答案 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.StartNew
和Parallel.ForEach
。每次在委托中添加async
修饰符时都必须谨慎。您必须确保被调用的方法能够理解异步委托,否则可能会导致异步空缺和它们造成的破坏。