WPF怎样在工作线程中更新窗体的UI元素Dispa
这是一个普遍的问题:如果我们再程序中使用了多线程技术,而工作线程(后台线程)如果需要更新界面上的元素(例如进度条等),就会有一个线程安全性问题,因为进度条是由主线程创建出来的。
关于这一点,大致上看,WPF的机制与Windows Forms是没有差别的。我们在Windows Forms中需要按照下面的方式更新窗体元素。
using System;using s;using ading;namespace WindowsFormsApplication1{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//错误的写法:直接更新new Thread(() =>{e = 10;})t();}private void button2_Click(object sender, EventArgs e){//正确的写法,通知主线程更新new Thread(()=>{ke(new Action(() =>{e = 10;}));})t();}}}
第一种是错误的写法,它将导致一个运行时错误
了解了这些,我们来看看WPF是怎么做的?
点击第一个按钮的话,我们同样会收到一个错误
点击第二个按钮,则工作正常
我们看看代码有什么区别
using System;using ows;using ading;namespace WpfApplication1{///
/// 的交互逻辑///
public partial class Window1 : Window{public Window1(){InitializeComponent();}private void button1_Click(object sender, RoutedEventArgs e){//错误的写法:直接更新new Thread(() =>{e = 20;})t();}private void button2_Click(object sender, RoutedEventArgs e){//正确的写法:通知主线程去完成更新new Thread(()=>{ke(new Action(()=>{e=20;}));})t();}}}
请注意,Window类并没有Invoke方法,这是与Form不一样的。取而代之的是,我们需要通过访问atcher属性,然后调用Invoke方法 。仅此而已
好吧,那么到底什么是Dispatcher呢?从字面上来说,它是所谓的接线员,或者调度员的`意思。这说明什么呢?每个线程都有一个唯一的调度员,我们在代码中所做的工作其实是向这个调度员发出指令,然后它再帮我们做。这样理解就对了。
我们的窗体是在主线程创建出来的,里面的控件自然也是如此。我们之前解释过WPF的应用程序也是单线程模型的(STAThread),所以整个应用程序里面会有一个默认的Dispatcher,它负责调度主线程的工作。
其实,如果大家真有兴趣,可以看看这个方法的实现,就能理解上面所说的话了
[SecurityCritical]internal int RunInternal(Window window){fyAccess();alTraceEvent(UNGUID, 0);if (this._appIsShutdown){throw new InvalidOperationException(("CannotCallRunMultipleTimes", new object[] { ype()Name }));}if (window != null){if (!kAccess()){throw new ArgumentException(("WindowPassedShouldBeOnApplicationThread", new object[] { ype()Name, ype()Name }));}if (!tem(window)){(window);}if (Window == null){Window = window;}if (bility != ble){nInvoke(, delegate (object obj) {(obj as Window)();return null;}, window);}}reHwndSource();if (!owserHosted){ispatcher(null);}return this._exitCode;}[SecurityCritical]private object RunDispatcher(object ignore){rt(!this._ownDispatcherStarted);this._ownDispatcherStarted = true;();return null;}那么,为什么在Window中可以调用到Dispatcher属性呢?或者说在那些对象上面可以采用这种机制呢?大致上说,几乎所有的控件都可以,因为他们的基类一般都可以追溯到一个DispatcherObject
从这个角度来说,如果我们自己编写一个用于WPF的控件,那么也是需要按照这样的层次结构去继承的。这样在控件内部,才可以通过atcher来更新一些界面元素了。
那么,如果我们是一个类库项目,就是一个标准的类型,它也需要更新到主线程中的一些元素怎么办?
此时可以通过acther来实现,例如下面的例子
using System;using ows;namespace WpfApplication1{public class WindowHelper{public static void SomeMethod() {ke(new Action(() => {e = "我修改过的窗体标题";}));}}}
其实,要认真讲的话,Application的这个Dispatcher与我们刚才用到的Window的Dispatcher是同一个对象。也就是说,每个线程只有一个。
而其实,使用Window的Dispatcher,与使用Button的Dispatcher也没有区别的
最后要说一点的是,Dispatcher除了Invoke方法之外,还有BeginInvoke方法。区别在于后者是异步执行的。如何使用异步的机制呢?
using System;using ows;using ading;namespace WpfApplication1{public class WindowHelper{public static void SomeMethod() {//ke(new Action(() => {// e = "我修改过的窗体标题";//}));var task = nInvoke(new Action(() => { e = "我修改过的窗体标题"; }));leted += new EventHandler(task_Completed);}static void task_Completed(object sender, EventArgs e){("任务已经完成");}}}
-
红领巾奖章二星章事迹简介
在日常学习、工作和生活中,大家都不可避免地要接触到事迹吧,根据范围的不同,事迹可分为集体事迹和个人事迹。想拟事迹却不知道该请教谁?以下是小编收集整理的红领巾奖章二星章事迹简介,希望对大家有所帮助。红领巾奖章二星章事迹简介1刘xx,女,现年10岁,威海高区黄家沟...
-
师德师风教育学习读书笔记(通用9篇)
当仔细品读一部作品后,相信大家一定领会了不少东西,让我们好好写份读书笔记,把你的收获和感想记录下来吧。千万不能认为读书笔记随便应付就可以,下面是小编为大家收集的师德师风教育学习读书笔记,仅供参考,大家一起来看看吧。师德师风教育学习读书笔记篇1教师是知识...
-
师德师风回头看总结范文(通用16篇)
总结是对某一特定时间段内的学习和工作生活等表现情况加以回顾和分析的一种书面材料,它是增长才干的一种好办法,因此十分有必须要写一份总结哦。那么你知道总结如何写吗?下面是小编收集整理的师德师风回头看总结范文(通用16篇),希望能够帮助到大家。师德师风回头看总...
-
小学师德师风自查报告(通用20篇)
在我们平凡的日常里,报告与我们的生活紧密相连,不同的报告内容同样也是不同的。一起来参考报告是怎么写的吧,下面是小编精心整理的小学师德师风自查报告,仅供参考,希望能够帮助到大家。小学师德师风自查报告1教育如镜亦如窗,这句话反映了教育实践既像一面镜子,又像一...
相关文章
- 英语报纸解读:Data may disrupt a peculiar business
- AndroidApp中使用SurfaceView制作多线程动画的实例讲解
- 高中英语作文ImpressiononKungFuPanda
- Wind is Power Potential Quantified的英语作文
- 英语报纸解读:Data may disrupt a peculiar business大纲
- win7中Windows Update下载如何关闭
- 高中英语作文:My approach to difficulties in learning
- PEP英语五年级上册评课稿 Unit 3 What’s your favourite food?
- WINDOWS和Linux上怎么安装php7 alpha 和 yaf
- JavaScript在Android的WebView中parseInt函数转换不正确