我在一个线程中运行一个非常耗时的方法,其中一件事就是,如果没有可用的图像,它会将名为Background的背景网格设置为纯色。以下是该代码段的外观:
SolidColorBrush scb = new SolidColorBrush();
scb.Color = Color.FromRgb(21, 21, 21);
Dispatcher.BeginInvoke(new Action(() => Background.Background = scb));
但我总是在这个地方遇到错误"Cannot use a DependencyObject that belongs to a different thread than its parent Freezable"
有谁知道为什么会这样? Dispatcher应该让这个问题消失,对吗?
以下是我如何调用方法(如果需要)
Thread BGthread = new Thread(HandleBackgrounds);
BGthread.Start();
答案 0 :(得分:4)
SolidColorBrush
是一个依赖项对象 - 您在非UI线程中创建它,然后尝试在UI线程中使用它。试试这个:
Action action = () =>
{
SolidColorBrush scb = new SolidColorBrush(Color.FromRgb(21, 21, 21));
Background.Background = scb;
};
Dispatcher.BeginInvoke(action);
当然只是在一个声明中:
Dispatcher.BeginInvoke((Action (() =>
Background.Background = new SolidColorBrush(Color.FromRgb(21, 21, 21)))));
无论哪种方式,您都会在您传递给调度员的操作中创建SolidColorBrush
。
答案 1 :(得分:1)
Brush
是DispatcherObject
,因此它具有线程关联性 - 它属于创建它的线程,通常只能由它使用。
但是,WPF有一个调度程序对象的子类,称为Freezable
,您可以通过将它们设置为只读来删除线程关联。画笔是可以冻结的,因此您可以在一个线程上创建一个并将其传递给另一个:
var scb = new SolidColorBrush(Color.FromRgb(21, 21, 21));
scb.Freeze();
Dispatcher.BeginInvoke(new Action(() => Background.Background = scb));
如果您在视图模型中创建未在UI线程上创建的画笔,则此选项非常有用。另一个常见的用例是在不同的线程上解码图像,这可以提高性能(ImageSource
也是可冻结的。)
冻结freezables也被视为performance optimization,因此请尽可能使用它。