WPF 线程操纵UI问题

WPF只允许UI线程修改UI,其他线程必须通过Invoke、委托(安全性)
Winform可以开启/关闭“只允许UI线程修改UI”

在WPF中非UI线程修改UI的方法:Dispatcher

非UI线程直接修改UI,会报错

System.InvalidOperationException:“调用线程无法访问此对象,因为另一个线程拥有该对象。”

正确的做法是使用Dispatcher
Dispatcher简单暴力,适合小工作量的修改一些界面内容
长期后台工作应该考虑使用BackgroundWorker,有很多相关功能库

Task t = new Task(() =>
{
	//wrong
	//NameLabel.Content = "我用非UI线程修改NameLabel的文字,失败了";

	NameLabel.Dispatcher.Invoke(new Action(delegate
	{
		NameLabel.Content = "我用UI线程修改了NameLabel的文字";
	}));
	Thread.Sleep(5000);
	this.Dispatcher.Invoke(new Action(() =>
	{
		NameLabel.Content = "我用UI线程修改了NameLabel的文字-2";
	}));
	Thread.Sleep(5000);
	this.Dispatcher.BeginInvoke(new Action(() =>
	{
		NameLabel.Content = "我用UI线程修改了NameLabel的文字-3";
	}));
});
t.Start();

Dispatcher使用一个专用的 UI 线程来完成界面的操作和更新,这个线程会关联一个唯一的WPF Dispatcher 对象,用于调度按优先顺序排列的工作项队列。Application.Run() 实际上就是对 Dispatcher.Run() 的间接调用。

WPF Dispatcher通过循环来处理工作项队列,这个循环通常被成为 "帧 (DispatcherFrame)"。Dispatcher.Run() 创建并启动这个帧,这也是 Application.Run() 启动消息循环的最终途径。

参考资料

线程处理模型

示例代码

ChangeUI

posted @ 2017-12-29 17:55  Lulus  阅读(644)  评论(0编辑  收藏  举报