DispatcherObject,Dispatcher,Thread之间的关系
我们都知道WPF中的控件类都是从System.Windows.Threading.DispatcherObject继承而来, 而DispatcherObject又在构造时与当前线程的Dispatcher关联起来,CurrentDispatcher如果为null则会主动new一个Dispatcher并且在构造时和当前创建它的线程关联起来了。因此整个链为DispatcherObject <- Dispatcher <- Thread. 具体我们一起看看反编译的红色代码:
public abstract class DispatcherObject
{
private Dispatcher _dispatcher;
[EditorBrowsable(EditorBrowsableState.Advanced)]
public Dispatcher Dispatcher
{
get
{
return this ._dispatcher;
}
}
protected DispatcherObject()
{
base .\u002Ector();
this ._dispatcher = Dispatcher.CurrentDispatcher;
}
........................................................
}
public sealed class Dispatcher
{
public static Dispatcher CurrentDispatcher
{
get
{
return Dispatcher.FromThread(Thread.CurrentThread) ?? new Dispatcher();
}
}
private Dispatcher()
{
.............................
Dispatcher._tlsDispatcher = this ;
this ._dispatcherThread = Thread.CurrentThread;
.............................
}
..............................
}
这样设计的原则就保证:界面元素只有被创建它的线程访问
Dispatcher中Invoke,BeginInvoke和Win32中SendMessage,PostMessage的关系
上面我们提到wpf的界面元素只有被创建它的线程来访问,如果我们想在后台或者其他线程里该怎么办?
答案就是利用Dispatcher的Invoke和BeginInvoke,作用就是把委托放到界面元素关联的Dispatcher里的工作项里,然后此Dispatcher关联的线程进行执行。
所不同的是Invoke是在关联的线程里同步执行委托, 而BeginInvoke是在关联的线程里异步执行委托。
做过Win32或者MFC编程的童鞋们都知道win32中有SendMessage和PostMessage类似的概念,这些概念有什么内在关系呢?
其实Dispatcher的Invoke和BeginInvoke都是调用Win32的PostMessage传递窗体句柄和消息号,反编译代码如下:
private bool RequestForegroundProcessing()
{
if (this._postedProcessingType >= 2)
return true;
if (this._postedProcessingType == 1)
SafeNativeMethods.KillTimer(new HandleRef((object) this, this._window.Value.Handle), 1);
this._postedProcessingType = 2;
return MS.Win32.UnsafeNativeMethods.TryPostMessage(new HandleRef((object) this, this._window.Value.Handle), Dispatcher._msgProcessQueue, IntPtr.Zero, IntPtr.Zero);
}
只不过Invoke在PostMessage后调用了内部返回值DispatcherOperation的wait方法,在执行结束后才返回。反编译代码如下:
DispatcherOperation dispatcherOperation = this.BeginInvokeImpl(priority, method, args, isSingleParameter);
if (dispatcherOperation != null)
{
int num = (int) dispatcherOperation.Wait(timeout);
if (dispatcherOperation.Status == DispatcherOperationStatus.Completed)
obj = dispatcherOperation.Result;
else if (dispatcherOperation.Status == DispatcherOperationStatus.Aborted)
obj = (object) null;
else
dispatcherOperation.Abort();
}
WPF的消息泵和Win32的消息泵之间的关系
WPF的窗体程序都必须隐式或者显式调用
Application.Run()来初始化WPF窗体。当Application.Run()调用时, 会在其内部调用Dispatcher.Run()方法。最终会在PushFrame()方法内初始化消息泵。
具体为:Application.Run() -> Dispatcher.Run() -> Dispatcher.PushFrame() -> Dispatcher.PushFrameImpl()
private void PushFrameImpl(DispatcherFrame frame)
{
MSG msg = new MSG();
++this._frameDepth;
try
{
SynchronizationContext current = SynchronizationContext.Current;
bool flag = current != this._dispatcherSynchronizationContext;
try
{
if (flag)
SynchronizationContext.SetSynchronizationContext((SynchronizationContext) this._dispatcherSynchronizationContext);
while (frame.Continue && this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
this.TranslateAndDispatchMessage(ref msg);
if (this._frameDepth != 1 || !this._hasShutdownStarted)
return;
this.ShutdownImpl();
}
finally
{
if (flag)
SynchronizationContext.SetSynchronizationContext(current);
}
}
finally
{
--this._frameDepth;
if (this._frameDepth == 0)
this._exitAllFrames = false;
}
}
Ok,从上述反编译的代码可以看到,WPF还是通过Dispatcher内部实现了传统的Win32消息循环, 如GetMessage,TranslateMessage,DispatchMessage。
下面是win32消息泵的实现, 大家可以对比下:
BOOL bRet;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
- 聊聊WPF中字体的设置
1. 今天帮同事调试一个字体的bug:TextBox中的中文显示大小不一致, 比如包含"杰","热". 原因是WPF针对点阵字体需要指定特定字体才能正确渲染, ...
- WPF:浅析Dispatcher
本人文笔差.还是直接上代码吧.(本文假设你对WPF中的Dispatcher有一定的了解) 你觉得下面的代码可以正常执行吗? private void Button_Click(object sende ...
- WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object)
原文 WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object) 众所周知的,WPF 中多数对象都继承自 Dispatch ...
- WPF 的 Application.Current.Dispatcher 中,Dispatcher 属性一定不会为 null
原文:WPF 的 Application.Current.Dispatcher 中,Dispatcher 属性一定不会为 null 在 WPF 程序中,可能会存在 Application.Curren ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
- MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信
MVVM模式解析和在WPF中的实现(五) View和ViewModel的通信 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 M ...
- 【WPF】 Timer与 dispatcherTimer 在wpf中你应该用哪个?
源:Roboby 1.timer或重复生成timer事件,dispatchertimer是集成到队列中的一个时钟.2.dispatchertimer更适合在wpf中访问UI线程上的元素 3.Dispa ...
- WPF线程(Step1)——Dispatcher
使用WPF开发时经常会遇上自己建立的线程需要更新界面UI内容,从而导致的跨线程问题. 异常内容: 异常类型:System.InvalidOperationException 异常描述: "S ...
- WPF中Timer与DispatcherTimer类的区别
前几天在WPF中写了一个轨迹回放的功能,我想稍微做过类似项目的,都晓得采用一个时间控件或者时间对象作为调度器,我在这么做的时候,出现了问题,于是将程序中的Timer换成了DispatchTimer,然 ...
随机推荐
- 跨平台移动开发_PhoneGap 使用Accelerometer 加速器
使用Accelerometer 加速器效果图 示例代码 <!DOCTYPE html> <html> <head> <title> Cude Phone ...
- samtools使用过程中出现的问题
1.EOP marker is absent 在使用samtools index时出现 EOF是指the end of file,即samtools认为你的bam文件是不完整的. 如果把view参数的 ...
- 20145240 《Java程序设计》第九周学习总结
20145240 <Java程序设计>第九周学习总结 教材学习内容总结 JBDC是用于执行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商对接口直接操作,开发人员无须接触底层数 ...
- Android LCD(一):LCD基本原理【转】
本文转载自:http://blog.csdn.net/longxiaowu/article/details/24787597 关键词:Android LCD TFT 液晶 偏光片 彩色滤光片 背光 ...
- ASP.NET MVC 5 访问在views文件夹中的JS文件。 ASP.NET MVC html与JS分离
修改VIEWS文件夹下的web.config文件, 加入下面红色字标识的内容: <system.webServer> <handlers> <r ...
- centos安装zabbix监控服务器端
首先安装zabbx 依赖yum install net-snmp-devel libxml2-devel libcurl-devel -y 下载zabbix 源码包wget https://ncu.d ...
- struts2发送ajax的几个问题(不使用struts2-json-plugin的情况下)
采用原始方式发送ajax到action时,会遇到get,post的不同,原因是ContentType的问题,ContentType必须是text/html,struts获取到的inputStream才 ...
- java应用线上CPU过高问题排查
1.top 命令,查看占用CPU最高的PID.ps aux|grep PID 进一步确定tomcat进程出现问题.2.ps -mp pid -o THREAD,tid,time显示线程列表3.prin ...
- 关于tcp的知识记录
1. 概念 TCP(Transmission Control Protocol,传输控制协议),是一种面向连接的,可靠地,基于字节流的传输层通信协议.当应用层向TCP层发送用于网络间传输的用8位字节表 ...
- Codeforces Round #386 (Div. 2) C D E G
一场比较简单的题 比较脑洞 C 如果坐车比较快的话 先走不如等车 所以最后的ans是min(纯走路,纯坐车) 讨论一下坐车时间 D 因为k一定是>=1的 所以当a=b的时候 GBGBGB这样间隔 ...