什么是父级Freezable?这个错误是什么意思?

11

我遇到了这个错误:

无法使用属于不同线程的 DependencyObject 的父级 Freezable

这是什么意思?它是英语吗?父级被冻结了还是只能被冻结?如果可以使错误消失,有没有办法使父级无法被冻结?

发生了什么:

我在 WPF 应用程序中有两个 OpenGL WinForms 控件,到目前为止,一切都很顺利(我想)。现在,我添加了一个更新,以便一个 WinForms 控件更新图像时,另一个控件也应该更新。那实际上曾经起作用,但现在我得到了那个错误。通过代码跟踪,崩溃会在随机位置发生,这让我相信这是个垃圾回收故障(即,在另一个线程中进行的某些更新正在创建某个将在随机时间进行垃圾回收的东西)。

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

我已经无从下手了。我该从哪里开始?

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

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

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


1
在编程中,有很少几种情况需要用到句子图解... - Brian Postow
1
标题措辞极差。没有任何相关关键词,因此无法通过搜索找到这个问题。这不是一个支持论坛,请适当地提出您的问题... - Timwi
1
嘿@Timwi,看看这个答案。我只是把这个问题留在这里,因为我确实找到了答案,但是过程非常令人沮丧。如果你想编辑标题,那就赚更多的声望并按照你认为应该的方式自己去做吧。 - mmr
1个回答

16

好的,我搞定了。通常情况下,我会直接删除这个问题,但是找到关于如何解决这个问题的信息真的很麻烦。

问题出在这个调用上:

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();
   }));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接