AutoResetEvent.WaitOne()导致死锁

霍恩海姆

我正在编写一个关键区域的应用程序。

我决定使用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#中asyncandawait模式了解IPC ,而且我对.Net世界中的线程不太熟悉。

我真的很想了解幕后的真实情况。感谢您的任何答复;)

阿尔加兹

您有一个死锁,因为WaitOne阻塞了主线程(在主线程上执行了按钮单击处理程序),而在调用时没有调用ConfigureAwait(false)await,这意味着它将尝试运行主线程之后的代码await。线程,即使它被阻止也可能导致死锁。

我建议阅读这篇文章,以更彻底地解释死锁情况。

对于您的代码,我建议将锁加深,可能在异步Task中,并尝试使用更合适的模式进行锁定,最好是lock语句,因为使用Event对象进行互斥是不便的,正如汉斯在评论中所述。 。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章