我只想在另一个线程中更改窗口的背景。 有两个程序,一个是工作正常,另一个是 InvalidOperationException。
正确的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thread t = new Thread(new ParameterizedThreadStart(threadTest));
t.Start(@"C:UsersPublicPicturesSample PicturesChrysanthemum.jpg");
}
void threadTest(object obj)
{
string path = obj as string;
this.Dispatcher.Invoke(new Func<object>(() => this.Background = new
}
}
错误代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thread t = new Thread(new ParameterizedThreadStart(threadTest));
t.Start(@"C:UsersPublicPicturesSample PicturesChrysanthemum.jpg");
}
void threadTest(object obj)
{
string path = obj as string;
//this.Dispatcher.Invoke(new Func<object>(() => this.Background = new ImageBrush(new BitmapImage(new Uri(path)))));
ImageBrush background = new ImageBrush(new BitmapImage(new Uri(path)));
this.Dispatcher.Invoke(new Func<object>(() => this.Background = background));
}
}
这些代码之间的区别在于,错误代码在子线程中创建 ImageBrush 对象。所以我的问题是:在 wpf 程序中,线程是否只能使用自己的线程创建的对象?感谢您的任何回复。
是的,你是对的。只有 UI 线程可以使用它创建的对象。因此,您可以使用调度程序在其正确线程上对 UI 操作"排队"。
回答你的第二个问题,当然,有一种方法可以将对象"传递"到 UI 线程。如果您看到(调度程序的)BeginInvoke结构,它是:
public DispatcherOperation BeginInvoke(
Delegate d,
params Object[] args
)
args 是参数对象数组的地方,就是放置参数的地方。
现在,如果您使用的是某些Freezable
对象(例如某些图像,画笔,变换或几何体),则需要在将其发送到UI线程之前进行object.Freeze();
。
是的,正确,这不仅是关于WPF
,而且总的来说,关于Windows programming
.
不能从不同于其自身的其他线程更新 UI 对象。
其原因很简单,因为必须保证消息泵送,尤其是传递到操作系统的目标控制。这对于使用SendMesage
进行通信自然有效,但对于PostMessage
也是如此。
如果您在单独的线程上创建一个对象,如果您先冻结它,则可以在 gui 线程上使用它。请参阅可冻结对象。