gpt4 book ai didi

c# - 为什么我不能在 lock 语句的主体中使用 'await' 运算符?

转载 作者:IT王子 更新时间:2023-10-29 03:28:15 30 4
gpt4 key购买 nike

不允许在 lock 语句中使用 C#(.NET Async CTP)中的 await 关键字。

来自 MSDN :

An await expression cannot be used in a synchronous function, in a query expression, in the catch or finally block of an exception handling statement, in the block of a lock statement, or in an unsafe context.

我认为由于某种原因,编译器团队很难或不可能实现这一点。

我尝试使用 using 语句来变通:

class Async
{
public static async Task<IDisposable> Lock(object obj)
{
while (!Monitor.TryEnter(obj))
await TaskEx.Yield();

return new ExitDisposable(obj);
}

private class ExitDisposable : IDisposable
{
private readonly object obj;
public ExitDisposable(object obj) { this.obj = obj; }
public void Dispose() { Monitor.Exit(this.obj); }
}
}

// example usage
using (await Async.Lock(padlock))
{
await SomethingAsync();
}

然而,这并没有像预期的那样工作。在 ExitDisposable.Dispose 中对 Monitor.Exit 的调用似乎无限期地(大部分时间)阻塞,导致死锁,因为其他线程试图获取锁。我怀疑我的变通方法的不可靠性与 lock 语句中不允许使用 await 语句的原因有某种关联。

有谁知道为什么 await 不允许出现在 lock 语句中?

最佳答案

I assume this is either difficult or impossible for the compiler team to implement for some reason.

不,实现起来一点也不困难或不可能 - 您自己实现的事实证明了这一事实。相反,这是一个非常糟糕的主意,因此我们不允许这样做,以防止您犯下这个错误。

call to Monitor.Exit within ExitDisposable.Dispose seems to block indefinitely (most of the time) causing deadlocks as other threads attempt to acquire the lock. I suspect the unreliability of my work around and the reason await statements are not allowed in lock statement are somehow related.

正确,您已经发现我们为什么将其定为非法。 在锁内等待是产生死锁的秘诀。

我相信您能明白原因:在 await 将控制权返回给调用者和方法恢复之间运行任意代码。该任意代码可能会取出产生锁顺序反转的锁,从而导致死锁。

更糟的是,代码可能会在另一个线程上恢复(在高级场景中;通常您会在执行等待的线程上再次启动,但不一定)在这种情况下,解锁将解锁一个锁在与取出锁的线程不同的线程上。这是一个好主意吗?没有。

我注意到,出于同样的原因,在 lock 中执行 yield return 也是“最糟糕的做法”。这样做是合法的,但我希望我们把它定为非法。我们不会对“等待”犯同样的错误。

关于c# - 为什么我不能在 lock 语句的主体中使用 'await' 运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7612602/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com