我正在编写一个关键区域的应用程序。
我决定使用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");
}
}
}
我有一个按钮,其click事件调用该Button_Click()
方法
它正常工作。但是,如果我足够快地在第一个通话Button_Click()
完成之前再次单击该按钮,则整个应用程序将停止响应。
在“调试”窗口中,我发现了类似的内容
Entering Button_Click
Entering Button_Click
该方法似乎永远无法完成。
我挣扎了一下,发现如果我改变lock.WaitOne();
为
if (!sync.WaitOne(TimeSpan.FromSeconds(1)))
{
return;
}
在这种情况下,我的应用程序可以避免死锁,但我不知道它为什么起作用。
我仅从我的OS课程和C#中的async
andawait
模式了解IPC ,而且我对.Net世界中的线程不太熟悉。
我真的很想了解幕后的真实情况。感谢您的任何答复;)
您有一个死锁,因为WaitOne
阻塞了主线程(在主线程上执行了按钮单击处理程序),而在调用时没有调用ConfigureAwait(false)await
,这意味着它将尝试运行主线程之后的代码await
。线程,即使它被阻止也可能导致死锁。
我建议阅读这篇文章,以更彻底地解释死锁情况。
对于您的代码,我建议将锁加深,可能在异步Task中,并尝试使用更合适的模式进行锁定,最好是lock语句,因为使用Event
对象进行互斥是不便的,正如汉斯在评论中所述。 。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句