Что такое родительский морозильник? Что означает эта ошибка?

Я получаю эту ошибку:

Нельзя использовать объект DependencyObject, принадлежащий другому потоку, чем его родительский Freezable

Что это значит? Это на английском? Является ли родитель замороженным, или он просто замораживается? Любой способ заставить родителя не замораживаться, если он заставляет ошибку уходить?

Что происходит:

У меня есть два элемента управления winforms в WPF-приложении, и до сих пор все работало плавно (я думаю). Теперь я добавил обновление, чтобы, когда один элемент управления winform обновляет изображение, другой должен также. Это действительно сработало, и теперь я получаю эту ошибку. Пошаговое выполнение кода происходит в случайных местах, что заставляет меня поверить, что это ошибка сборки мусора (т.е. Некоторое обновление в другом потоке создает что-то, что собирает мусор, и эта коллекция происходит в случайное время).

Исключение попадает в метод основного запуска и исключение InvalidOperationException.

Я хватаюсь за соломинку здесь. С чего начать?

EDIT: похоже, что вызов, вызывающий проблему, следующий:

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

Я все еще отслеживаю его; если эта серия строк закомментирована, все равно происходит сбой, и состояние потока имеет "только что закончившийся" поток (следовательно, предположение о сборке мусора).

Ответ 1

Хорошо, я понял это. Обычно я просто удалял этот вопрос, но было больно найти какую-либо информацию о том, как исправить это.

Проблема заключалась в вызове, который выглядел так:

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