从主线程和工作线程WPF中的死锁

时间:2017-03-10 16:01:48

标签: c# wpf multithreading locking

我有这样的代码:

private static var Locker = new Object();

private void SensitiveCode()
{
    lock (Locker)
    {
        SomeCodeSensitive(); .....
        Dispatcher.BeginInvoke(new Action(() =>
        {
            SomeCodeThatUpdatesUI();
        }));
        MoreCodeSensitive();
    }
}

我也有一个线程正在运行这样的事情:

while (X)
{
    SensitiveCode();
    Thread.Sleep(5000);
}

现在在我的主线程中,我有时会调用SensitiveCode(); SensitiveCode()处于锁定状态,因为它不能同时从2个线程调用。

嗯,问题是我不知道为什么,有时我发现死锁,有时在UI(UI冻结),有时在线程上。我不知道发生了什么,其中一个线程在lock()中停止,因为它应该是变量" Locker"正在使用另一个线程,但事实并非如此。我认为问题可能是锁内的BeginInvoke,但我认为这不足以锁定此代码。

此外,很难重现这个问题,我已经测试了3个小时,它只出现了2次。

有人知道它会是什么吗?

谢谢!

更新由于问题:

SensitiveCode()正在处理一些AsyncObservableCollection对象(来自http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/的类)。

执行从数据库读取和填充AsyncObservableCollection()等操作。我锁定了这个动作,因为当用户同时执行时,我不能允许线程更新我的AsyncObservableCollection。

此外,用户界面执行此操作

Dispatcher.BeginInvoke(new Action(() =>
        {
            if (tables.Count != TablesInWindow.Count)               
                TablesInWindow.ClearAndAddRange(tables);                
            else
            {
                if (tables.Where((t, i) => !TablesInWindow[i].Equals(t)).Any())                                            
                    TablesInWindow.ClearAndAddRange(tables);

            }

            ButtonPageBack.IsEnabled = canGoBack;
            ButtonPageNext.IsEnabled = canGoFoward;
        }));

更新2:

再做一次之后,这里是发生死锁的线程的截图

http://i.imgur.com/8xyIy6h.png

MovePageForward是我在UI上执行的操作,它包含以下代码:

public static void MakePageForward()
    {            
        lock (ConfigParameters.Lock)
        {
            _currentPage++;
            ShowTablesInWindow();
        }
    }

TimerConnectionTick具有以下代码:

private static void TimerConnectionTick()
    {
        while (!_thisDisposing)
        {
            ShowTablesInWindow();

            if (!_thisDisposing)
                Thread.Sleep(5000);
        }
    }

1 个答案:

答案 0 :(得分:0)

如果没有看到所有代码,就很难调试。您的SomeCodeThatUpdatesUI()方法中的某个位置是否也可能触发对Locker的锁定?如果你以递归方式触发锁定它会毫无问题地通过,但是如果你在Dispatcher线程的BeginInvoke中这样做(这可能与你提到的当前线程不同,你从不同的线程调用它),它会锁定并造成死锁。

如果是这种情况,也许您可​​以在需要锁定时进行重构,或使用类似ReaderWriterLockSlim(https://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx

的内容