本人文笔差。还是直接上代码吧。(本文假设你对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. Unity3D Input按键系统

    默认输入轴: Horizontal 和 Vertical被映射到w, a, s, d键和方向键 Fire1, Fire2, Fire3被分别映射到Ctrl,Option(Alt)和Command键 M ...

  2. cshtml中正则表达式使用后台代码

    //定义变量 bool a = false; //正则表达式 string b = @" ^ (13[0 - 9] | 14[5 | 7] | 15[0 | 1 | 2 | 3 | 5 | ...

  3. DataPipeline丨金融行业如何统一管理单个任务下所有API的同步情况

    目前,依靠"手工人力"的电子表格数据治理模式逐渐被"自动智能"的专业工具取代.数据管理员.业务分析师开始采用"平台工具"来梳理主数据.元数据 ...

  4. apache-jmeter-5.0的简单压力测试使用方法

    同事交接工作,压测部分交给我,记录一下使用方法 我将下载下来的压缩包解压后放置在E盘 然后配置环境变量: 变量名JMETER_HOME,变量值 E:\javatool\apache-jmeter-5. ...

  5. Ftp修改为主被动模式命令

    FTP是有两种数据连接模式的,主动模式和被动模式. PORT(主动)方式:客户端向服务器的FTP端口(默认是21)发送连接请求,服务器接受连接,建立一条命令链路.当需要传送数据时,客户端在命令链路上用 ...

  6. 通过命令行设置Windows 时区

    我们在进行自动测试的时候,不同的测试程序对于时区的要求不同,所以在开始的时候需要根据测试程序的要求了设置时区. Windows 提供了一个工具来进行时区设置.tzutil.exe. 目录:C:\Win ...

  7. OKR能解决996吗?德鲁克怎么看?

    最近网络上热议的“996”,不由让人想起我们的邻国日本.他们在20年前就有过一个热词“过劳死”,就是职场加班太严重导致的猝死. 最近有一本书新书<过劳时代>,说的就是日本20年前的过劳死. ...

  8. 微信小程序之onLaunch与onload异步问题

    所述问题: 前端时间开发了一个微信小程序商城项目,因为这个项目我们的需求是进入小程序就通过wx.login({}) 这个api进行用户登录,获取系统后台的用户基本信息.再此之前,一直以为微信小程序中的 ...

  9. 学python走过的坑 二 element与elements的却别

    1.sel = driver.find_elements_by_xpath('//*[@id="nr"]')# 搜索结果显示条数2.sel = driver.find_elemen ...

  10. C语言中的神兽strdup

    C语言的确博大精深,在C语言的世界中遨游了那么多年,发现自己仍是菜鸟一枚,很多利器没有能够驾驭,今天介绍一个神兽,威力无比,但是却很少人能用得好. 函数原型: #include <string. ...