Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 来自主线程和工作线程的WPF死锁_C#_Wpf_Multithreading_Locking - Fatal编程技术网

C# 来自主线程和工作线程的WPF死锁

C# 来自主线程和工作线程的WPF死锁,c#,wpf,multithreading,locking,C#,Wpf,Multithreading,Locking,我有这样一个代码: private static var Locker = new Object(); private void SensitiveCode() { lock (Locker) { SomeCodeSensitive(); ..... Dispatcher.BeginInvoke(new Action(() => { SomeCodeThatUpdatesUI(); }

我有这样一个代码:

private static var Locker = new Object();

private void SensitiveCode()
{
    lock (Locker)
    {
        SomeCodeSensitive(); .....
        Dispatcher.BeginInvoke(new Action(() =>
        {
            SomeCodeThatUpdatesUI();
        }));
        MoreCodeSensitive();
    }
}
while (X)
{
    SensitiveCode();
    Thread.Sleep(5000);
}
另外,我有一个线程正在运行,执行以下操作:

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();SensiveCode()处于锁定状态,因为不能同时从2个线程调用它

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

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

有人知道会是什么吗

谢谢

更新由于以下问题:

SensiveCode()正在处理一些AsyncObservableCollection对象(来自的类)

执行诸如从数据库读取和填充AsyncObservableCollection()之类的操作。我锁定此操作,因为我不能允许线程在用户同时更新AsyncObservableCollection

此外,UI也可以做到这一点

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:

再次执行后,下面是死锁发生时线程的屏幕截图

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

public static void MakePageForward()
    {            
        lock (ConfigParameters.Lock)
        {
            _currentPage++;
            ShowTablesInWindow();
        }
    }
TimerConnectionTick具有以下代码:

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

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

如果看不到所有代码,就很难进行调试。是否可能在SomeCodeThatUpdateUI()方法中的某个地方也触发了锁定锁?如果以递归方式触发锁,它将毫无问题地通过,但是如果在调度程序线程上的BeginInvoke中执行此操作(可能与您提到的当前线程不同,您从不同的线程调用它),它将锁定并导致死锁


如果是这样的话,也许您可以在需要锁定时重构,或者使用ReaderWriterLockSlim()之类的工具。

您使用的是什么,而不是使用Dispatcher。调用或锁定调用堆栈下面的某个位置(在某些代码敏感或更代码敏感的部分)?您能为示例添加更多上下文吗,可以用来重现问题的东西。
lock
thread.Sleep
都会阻止任何线程试图进入,同样需要更多的上下文。有几个奇怪的地方:
Dispatcher
不是敏感代码为什么会被锁定?而且
Locker
不是敏感对象为什么它用于锁,锁块内接触了多少敏感对象?无调度程序。调用SensitiveCode中的代码。那么。。。这不是敏感代码,我可以把它从锁里拿出来,但我不知道为什么它会有帮助。无论如何,我的问题是我不能重现这个问题。我在5个小时的测试中经历了3次,真是头疼。我会尝试将BeginInvoke代码发送给客户,以便他们在真实环境中测试它,因为我不知道还有什么要做。。。Locker是我用来锁定的对象,它不敏感,只是一个新对象()。我在敏感代码中涉及的是对数据库的调用和更新AsyncObservableCollection对象。更新的问题有更多信息我看到了您的更新,但是我只能猜测您的代码的其余部分在做什么,以及每个锁有多少入口点。您确定锁柜上发生了死锁吗?如果可以再次发生,请从进程中捕获转储文件并查看活动线程的调用堆栈。是的,我这样做了,并查看了我链接的图像: