我正在编写一个关键区域的应用程序。
我决定使用AutoResetEvent来实现互斥。
这是代码
public class MyViewModel
{
private AutoResetEvent lock = new AutoResetEvent(true);
private aync Task CriticalRegion()
{
Dosomething();
}
public async Task Button_Click()
{
Debug.WriteLine("Entering Button_Click");
lock.WaitOne();
try
{
await CriticalRegion();
}
finally
{
lock.Set();
Debug.WriteLine("Leaving Button_Click");
}
}
}
我有一个按钮,其点击事件调用了
Button_Click()
方法它正常工作。但是,如果在第一次调用
Button_Click()
完成之前,我足够快地再次单击该按钮,则整个应用程序将停止响应。在“调试”窗口中,我发现了类似的内容
Entering Button_Click
Entering Button_Click
该方法似乎永远无法完成。
我挣扎了一下,发现如果我将
lock.WaitOne();
更改为 if (!sync.WaitOne(TimeSpan.FromSeconds(1)))
{
return;
}
在这种情况下,我的应用程序可以避免死锁,但是我不知道它为什么起作用。
我仅从我的OS类(class)以及C#中的
async
和await
模式了解IPC,而且我对.Net世界中的线程不太熟悉。我真的很想了解幕后的真实情况。
感谢您的任何答复;)
最佳答案
您有一个死锁,因为WaitOne
阻塞了主线程(在主线程上执行了按钮单击处理程序),而您在调用await
时没有调用ConfigureAwait(false),这意味着它试图在主线程上运行await
之后的代码线程,即使它被阻止也可能导致死锁。
我建议阅读this post以更彻底地说明死锁情况。
对于您的代码,我建议将锁加深,可能在异步Task中,并尝试使用更合适的模式进行锁定,最好是lock statement,因为使用Event
对象互斥是不便的,正如汉斯在评论中指出的那样。 。
关于c# - AutoResetEvent.WaitOne()导致死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38971043/