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

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

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

最佳答案

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

我建议阅读this post以更彻底地说明死锁情况。

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

关于c# - AutoResetEvent.WaitOne()导致死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38971043/

10-17 00:13