WPF:浅析Dispatcher
本人文笔差。还是直接上代码吧。(本文假设你对WPF中的Dispatcher有一定的了解)
你觉得下面的代码可以正常执行吗?
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(() =>
{
while (true)
{
new Window().Show();
Thread.Sleep();
}
});
t.Start();
}
WPF的操作UI的线程必须是单线程单元模型(STA),也就是必须把线程的单元状态设置为STA才可以操作UI对象。
上面的代码,并没有设置线程的单元状态,线程的默认单元状态为:System.Threading.ApartmentState.Unknown
通过下面的代码可以设置线程的单元状态为STA:
t.TrySetApartmentState(ApartmentState.STA);
修改后的代码如下:(可以正常运行)
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(() =>
{
while (true)
{
new Window().Show();
Thread.Sleep();
}
});
t.TrySetApartmentState(ApartmentState.STA);
t.Start();
}
接下来,对代码再做一点修改,你觉得下面的代码是否可以正常运行呢?
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(() =>
{
while (true)
{
Window win = new Window(); this.Dispatcher.Invoke(new Action(delegate
{
win.Show();
}));
Thread.Sleep();
}
}); t.TrySetApartmentState(ApartmentState.STA);
t.Start();
}
在一个线程中创建的UI对象,也只能是创建该UI对象的线程才能访问它。如果其他线程要访问这个UI对象,需要通过创建UI线程的Dispatcher才能实现。
上面的代码,win对象实际上是t这个线程创建的。而执行win.Show()这个动作的却是另外这个线程(实际上是主UI线程),所以上面的代码也是不能正常执行的。
需要注意的是,只有当一个线程中执行过UI操作后,这个线程才具有Dispatcher,然后其他线程可以通过这个Dispatcher去访问该线程创建的UI对象。一个没有执行任何UI操作的线程,其Dispatcher为null.
通过Dispatcher的静态方法FromThread可以获取一个线程关联的Dispatcher对象。如果你觉得上面的这句话不好理解,可以看看下面的图:

看以看到,在没有执行UI操作之前,线程t的Dispatcher对象的值为null,当执行完Window win = new Window();后(也就是执行了一个UI操作),t线程关联的Dispatcher就有值了。
总结:
- 任何线程中如果想执行UI操作,那么其线程单元必须设置为STA。
- 一个线程如果创建了UI对象,那么这个UI对象就只能被这个线程管理。
- 任何线程如果需要访问其他的线程创建的UI对象,只能通过其他线程的Dispatcher进行访问
- 一个线程如果没有执行任何UI操作,那么其关联的Dispatcher为null
WPF:浅析Dispatcher的更多相关文章
- WPF 线程 Dispatcher
WPF 应用程序从两个线程开始: 一个用于处理呈现 一个用于管理 UI 呈现线程有效地隐藏在后台运行,而UI线程则接收输入.处理事件.绘制屏幕以及运行应用程序代码. 大多数应用程序都使用一个 UI 线 ...
- WPF中Dispatcher未捕获异常之处理
在UI线程中 在APP.XAML中定义 DispatcherUnhandledException事件 在工作线程中 PageMain.GetInstance().Dispatcher.Invoke(( ...
- 【WPF】Dispatcher及线程操作
WPF 应用程序启动后,会有两个线程: 1. 一个是用来处理UI呈现(处理UI的请求,比如输入和展现等操作). 2. 一个用来管理 UI的 (对UI元素及整个UI进行管理). 像Winform一样,W ...
- wpf 的dispatcher
wpf项目中后台代码调用界面控件时,会提示进程调用的错误. private Thread JxThread = null; //定义线程 private DataLoading.Loading nL ...
- WPF基础:Dispatcher介绍
Disaptcher作用 不管是WinForm应用程序还是WPF应用程序,实际上都是一个进程,一个进程可以包含多个线程,其中有一个是主线程,其余的是子线程.在WPF或WinForm应用程序中,主线程负 ...
- 调用线程无法访问此对象,因为另一个线程拥有该对象 [c# wpf定时器程序报的错误]
WPF:Dispatcher.Invoke 方法,只有在其上创建 Dispatcher 的线程才可以直接访问DispatcherObject.若要从不同于在其上创建 DispatcherObject ...
- WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变
本文说明WPF [调用线程无法访问此对象,因为另一个线程拥有该对象.] 解决方案以及如何实现字体颜色的渐变 先来看看C#中Timer的简单说明,你想必猜到实现需要用到Timer的相关知识了吧. C# ...
- 2018-2-13-wpf-使用-Dispatcher.Invoke-冻结窗口
title author date CreateTime categories wpf 使用 Dispatcher.Invoke 冻结窗口 lindexi 2018-2-13 17:23:3 +080 ...
- .Net中的AOP系列之《间接调用——拦截方法》
返回<.Net中的AOP>系列学习总目录 本篇目录 方法拦截 PostSharp方法拦截 Castle DynamicProxy方法拦截 现实案例--数据事务 现实案例--线程 .Net线 ...
随机推荐
- Gradle中的闭包
Gradle是基于Groovy的DSL基础上的构建工具,Gradle中的闭包,其原型上实际上即Groovy中闭包.而在表现形式上,其实,Gradle更多的是以约定和基于约定基础上的配置去展现.但本质上 ...
- javascript入门篇(六、正则表达式)
JavaScript 正则表达式 正则表达式是由一个字符序列形成的搜索模式.当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容. 正则表达式可以是一个简单的字符,或一个更复杂的模式.正则表达 ...
- Java PDF页面设置——页面大小、页边距、纸张方向、页面旋转
下面的示例将介绍通过Java编程来对PDF页面进行个性化设置的方法,包括设置页面大小.页边距.纸张方向.页面旋转等.这里有如下多种页面大小尺寸可供选择: 同时,设置文档内容旋转时,可支持如下角度进行内 ...
- gitbook 入门教程之前置知识
markdown 基本知识 markdown 是一种简化的 html 语法,相比于 txt 无格式文本更强大. 你可以用专门的软件去编辑 markdown 文件,就像需要使用软件编辑 txt 文件一样 ...
- 使用d3.v5实现折线图与面积图
d3最新是V5版的,比起V2的API变动了不少,写下我实现过程 效果图: 面积图: 折线图: 目录结构: <!DOCTYPE html> <html lang="en&qu ...
- bootstap初识之css
老师的博客:https://www.cnblogs.com/liwenzhou/p/8214637.html bootstrap中文网:http://www.bootcss.com/ 官网:https ...
- 【工具篇】Sublime Text 2 安装汉化破解、插件包安装教程详解
Sublime Text概述: Sublime Text是一个代码编辑器,也是HTML和散文先进的文本编辑器. 漂亮的用户界面和非凡的功能,例如:迷你地图,多选择,Python插件,代码段等等. 完全 ...
- 【Python实践-3】汉诺塔问题递归求解(打印移动步骤及计算移动步数)
# -*- coding: utf-8 -*- #汉诺塔移动问题 # 定义move(n,a,b,c)函数,接受参数n,表示3个柱子A.B.C中第1个柱子A的盘子数量 # 然后打印出把所有盘子从A借助B ...
- MySQL学习(三)主备分库分表和恢复数据 --- 2019年2月
1.MySQL主备切换 readonly 设置对超级(super)权限是无效的,而用于同步更新的线程,就拥有超级权限. 建议在做主备数据库的时候,将备用数据库设置为只读.(反向用readonly来判断 ...
- 初始hibernate 和环境搭建
hibernate是一个开源的数据持久化框架. hibernate的优点: hibernate进行操作数据库提高了代码的开发速度,大大降低了代码量,降低了维护成本. hibernate支持许多面向对象 ...