什么是父冻结? 这个错误是什么意思?

发布于 2024-07-21 20:46:51 字数 886 浏览 2 评论 0原文

我收到此错误:

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

这意味着什么? 是英文的吗? 父级是冻结的,还是只是可冻结的? 如果可以使错误消失,有什么方法可以使父级不可冻结吗?

发生了什么:

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

该异常是在 main run 方法中捕获的,它是一个 InvalidOperationException。

我在这里抓住救命稻草。 我从哪说起呢?

编辑:看起来导致问题的电话是这个:

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

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

I'm getting this error:

Cannot use a DependencyObject that belongs to a different thread than
its parent Freezable

What does that even mean? Is it in English? Is the parent frozen, or is it just freezable? Any way to make a parent not freezable, if it makes the error go away?

What's happening:

I have two opengl winforms controls in a WPF app, and so far, everything's been working smoothly (I think). Now, I've added an update so that when one winform control updates the image, the other should as well. That actually used to work, and now I'm getting that error. Stepping through the code has the crash happen in random places, which leads me to believe that it's a garbage collection fault (ie, some update in another thread is creating something that's getting garbage collected, and that collection happens at a random time).

The exception is caught in the main run method, and it's an InvalidOperationException.

I'm grasping at straws here. Where do I start?

EDIT: It looks like the call that's causing the problem is this one:

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

I'm still tracking it down; if that series of lines is commented out, the crash still happens, and the thread status has a 'just ended' thread (hence the garbage collection assumption).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

恬淡成诗 2024-07-28 20:46:51

好吧,我已经弄清楚了。 通常,我只是删除这个问题,但找到有关如何解决此问题的任何信息很痛苦。

问题是一个如下所示的调用:

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

OK, I've figured it out. Ordinarily, I'd just delete this question, but it was a pain to find any information about how to fix this.

The problem was a call that looked like this:

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

But! if you do that, then the dispatcher works, and then it tries to delete the brush, but the brush itself is also apparently getting deleted in another location.

So, the take-home lesson is, if you declare an ImageBrush, then delete it in the same thread, like so:

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();
   }));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文