11

我收到此错误:

不能使用属于与其父 Freezable 不同的线程的 DependencyObject

那有什么意思?是英文的吗?父母是冻结的,还是只是可冻结的?如果它使错误消失,有什么方法可以使父母不可冻结?

发生了什么:

我在一个 WPF 应用程序中有两个 opengl winforms 控件,到目前为止,一切都很顺利(我认为)。现在,我添加了一个更新,这样当一个 winform 控件更新图像时,另一个也应该更新。这实际上曾经有效,现在我得到了那个错误。单步执行代码会在随机位置发生崩溃,这让我相信这是垃圾收集错误(即,另一个线程中的某些更新正在创建正在收集垃圾的东西,并且该收集是在随机时间发生的)。

异常在主运行方法中被捕获,它是一个 InvalidOperationException。

我在这里抓着稻草。我从哪里开始?

编辑:看起来导致问题的调用是这个:

        if (imagePanel.InvokeRequired)
        {
            imagePanel.Invoke(new System.Windows.Forms.MethodInvoker(delegate{
                imagePanel.ClearImages();
            }));
        }
        else
        {
            imagePanel.ClearImages();
        }

我仍在追踪它;如果这一系列行被注释掉,崩溃仍然会发生,并且线程状态有一个“刚刚结束”的线程(因此是垃圾收集假设)。

4

1 回答 1

15

好的,我已经想通了。通常,我会删除这个问题,但很难找到有关如何解决此问题的任何信息。

问题是一个看起来像这样的调用:

ImageBrush theBrush = new ImageBrush(new Bitmap(new Uri(...)));

if (labelStatus.Dispatcher.Thread == System.Threading.Thread.CurrentThread) {
    button.background = theBrush;
}
else {
   labelStatus.Dispatcher.BeginInvoke((System.Threading.ThreadStart)(delegate {
    button.background = theBrush;
   }));
}

但!如果你这样做,那么调度程序就会工作,然后它会尝试删除画笔,但画笔本身显然也在另一个位置被删除。

所以,带回家的教训是,如果你声明一个 ImageBrush,然后在同一个线程中删除它,如下所示:

void MyFunc(){
     ImageBrush theBrush = new ImageBrush(new Bitmap(new Uri(...)));
     button.background = theBrush;
}

if (labelStatus.Dispatcher.Thread == System.Threading.Thread.CurrentThread) {
    MyFunc();
}
else {
   labelStatus.Dispatcher.BeginInvoke((System.Threading.ThreadStart)(delegate {
       MyFunc();
   }));
}
于 2009-05-14T19:01:00.670 回答