本人文笔差。还是直接上代码吧。(本文假设你对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就有值了。

总结:

  1. 任何线程中如果想执行UI操作,那么其线程单元必须设置为STA。
  2. 一个线程如果创建了UI对象,那么这个UI对象就只能被这个线程管理。
  3. 任何线程如果需要访问其他的线程创建的UI对象,只能通过其他线程的Dispatcher进行访问
  4. 一个线程如果没有执行任何UI操作,那么其关联的Dispatcher为null

WPF:浅析Dispatcher的更多相关文章

  1. WPF 线程 Dispatcher

    WPF 应用程序从两个线程开始: 一个用于处理呈现 一个用于管理 UI 呈现线程有效地隐藏在后台运行,而UI线程则接收输入.处理事件.绘制屏幕以及运行应用程序代码. 大多数应用程序都使用一个 UI 线 ...

  2. WPF中Dispatcher未捕获异常之处理

    在UI线程中 在APP.XAML中定义 DispatcherUnhandledException事件 在工作线程中 PageMain.GetInstance().Dispatcher.Invoke(( ...

  3. 【WPF】Dispatcher及线程操作

    WPF 应用程序启动后,会有两个线程: 1. 一个是用来处理UI呈现(处理UI的请求,比如输入和展现等操作). 2. 一个用来管理 UI的 (对UI元素及整个UI进行管理). 像Winform一样,W ...

  4. wpf 的dispatcher

    wpf项目中后台代码调用界面控件时,会提示进程调用的错误. private Thread JxThread = null;  //定义线程 private DataLoading.Loading nL ...

  5. WPF基础:Dispatcher介绍

    Disaptcher作用 不管是WinForm应用程序还是WPF应用程序,实际上都是一个进程,一个进程可以包含多个线程,其中有一个是主线程,其余的是子线程.在WPF或WinForm应用程序中,主线程负 ...

  6. 调用线程无法访问此对象,因为另一个线程拥有该对象 [c# wpf定时器程序报的错误]

    WPF:Dispatcher.Invoke 方法,只有在其上创建 Dispatcher 的线程才可以直接访问DispatcherObject.若要从不同于在其上创建 DispatcherObject ...

  7. WPF [调用线程无法访问此对象,因为另一个线程拥有该对象。] 解决方案以及如何实现字体颜色的渐变

    本文说明WPF [调用线程无法访问此对象,因为另一个线程拥有该对象.] 解决方案以及如何实现字体颜色的渐变 先来看看C#中Timer的简单说明,你想必猜到实现需要用到Timer的相关知识了吧. C# ...

  8. 2018-2-13-wpf-使用-Dispatcher.Invoke-冻结窗口

    title author date CreateTime categories wpf 使用 Dispatcher.Invoke 冻结窗口 lindexi 2018-2-13 17:23:3 +080 ...

  9. .Net中的AOP系列之《间接调用——拦截方法》

    返回<.Net中的AOP>系列学习总目录 本篇目录 方法拦截 PostSharp方法拦截 Castle DynamicProxy方法拦截 现实案例--数据事务 现实案例--线程 .Net线 ...

随机推荐

  1. Gradle中的闭包

    Gradle是基于Groovy的DSL基础上的构建工具,Gradle中的闭包,其原型上实际上即Groovy中闭包.而在表现形式上,其实,Gradle更多的是以约定和基于约定基础上的配置去展现.但本质上 ...

  2. javascript入门篇(六、正则表达式)

    JavaScript 正则表达式 正则表达式是由一个字符序列形成的搜索模式.当你在文本中搜索数据时,你可以用搜索模式来描述你要查询的内容. 正则表达式可以是一个简单的字符,或一个更复杂的模式.正则表达 ...

  3. Java PDF页面设置——页面大小、页边距、纸张方向、页面旋转

    下面的示例将介绍通过Java编程来对PDF页面进行个性化设置的方法,包括设置页面大小.页边距.纸张方向.页面旋转等.这里有如下多种页面大小尺寸可供选择: 同时,设置文档内容旋转时,可支持如下角度进行内 ...

  4. gitbook 入门教程之前置知识

    markdown 基本知识 markdown 是一种简化的 html 语法,相比于 txt 无格式文本更强大. 你可以用专门的软件去编辑 markdown 文件,就像需要使用软件编辑 txt 文件一样 ...

  5. 使用d3.v5实现折线图与面积图

    d3最新是V5版的,比起V2的API变动了不少,写下我实现过程 效果图: 面积图: 折线图: 目录结构: <!DOCTYPE html> <html lang="en&qu ...

  6. bootstap初识之css

    老师的博客:https://www.cnblogs.com/liwenzhou/p/8214637.html bootstrap中文网:http://www.bootcss.com/ 官网:https ...

  7. 【工具篇】Sublime Text 2 安装汉化破解、插件包安装教程详解

    Sublime Text概述: Sublime Text是一个代码编辑器,也是HTML和散文先进的文本编辑器. 漂亮的用户界面和非凡的功能,例如:迷你地图,多选择,Python插件,代码段等等. 完全 ...

  8. 【Python实践-3】汉诺塔问题递归求解(打印移动步骤及计算移动步数)

    # -*- coding: utf-8 -*- #汉诺塔移动问题 # 定义move(n,a,b,c)函数,接受参数n,表示3个柱子A.B.C中第1个柱子A的盘子数量 # 然后打印出把所有盘子从A借助B ...

  9. MySQL学习(三)主备分库分表和恢复数据 --- 2019年2月

    1.MySQL主备切换 readonly 设置对超级(super)权限是无效的,而用于同步更新的线程,就拥有超级权限. 建议在做主备数据库的时候,将备用数据库设置为只读.(反向用readonly来判断 ...

  10. 初始hibernate 和环境搭建

    hibernate是一个开源的数据持久化框架. hibernate的优点: hibernate进行操作数据库提高了代码的开发速度,大大降低了代码量,降低了维护成本. hibernate支持许多面向对象 ...