What is a parent freezable? What does this error mean?
Asked Answered
M

1

11

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).

Mercurialize answered 14/5, 2009 at 18:39 Comment(3)
One of the few cases where diagramming a sentence would be helpful...Englis
Extremely bad title wording. Nobody can find this question by searching for any relevant keywords, because none are in the title. This is not a support forum, formulate your questions properly...Fascista
Hey @Timwi, read the answer. Realize that I only left this question here because I did find the answer, but it was extremely frustrating. If you want to edit the title, get more rep and do it yourself for how you think it should be.Mercurialize
M
16

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();
   }));
}
Mercurialize answered 14/5, 2009 at 19:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.