【发布时间】:2020-05-14 23:58:38
【问题描述】:
在我的代码中,我假设outerFlag 将在innerFlag 之后被击中,但实际上它运行起来就像火了然后忘记了(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 而不使用 Lock 方法但通过直接 lambda 时,它按预期工作。
有人可以解释这种行为吗?
【问题讨论】:
-
那是因为
Lock接受了一个委托,在你的情况下这个委托返回一个任务。但是您不会等待该任务,因此这是一项“一劳永逸”的任务。基本上你只需通过await Lock(...)爆炸,并且委托内部的 2 秒延迟将等待然后将 innerFlag 设置为 true,但你已经忽略了该任务并继续执行。 -
如果你把
Lock改成private async Task Lock(Func<Task> func) { await func(); },效果可能会更好。 -
这能回答你的问题吗? await Task.Delay() vs. Task.Delay().Wait()
-
当然它运行起来就像火了然后忘记了——你将
Task-returning 方法传递给吃Action的东西,这意味着这样产生的任务被忽略了。从本质上讲,你得到的正是你所要求的。 (请注意,如果您想要实际的锁定/排除,这绝对不是,您想使用SemaphoreSlim或AsyncLock之类的东西 - 不要尝试使用您自己的布尔标志在这里重新发明轮子,因为这几乎当然会遇到一些微妙的错误。) -
@defaultlocale 不,你的问题没有回答这个问题
标签: c# .net asynchronous async-await task