wpf探秘之B哥Dispatcher私房菜(2)最终回

上次我们说到Dispatcher内部有一个管理DO的队列,我暂且称之为DOQueue,在本文我就来重点说DO的处理机制,首先我们来看看DO是怎样被创建的,wpf并没有改变太多win32的内核,消息循环的机制已经深入人心了,同样窗体还是有自己的消息循环,如上面介绍win32时,消息循环的处理者肯定为一个窗体过程函数WndProc,以前我们直接把我们回调写到这个函数里面在窗体中注册下就完事大吉了,然而现在wpf封装了这个操作,毕竟对于它来说,所有的函数指针 都是不安全的存在,不能用函数指针,要实现回调就只能依靠委托了,所以过程函数把自己要干的事情在内部包装成一个委托的形式(就是不让用户自己来操作指针),调用一个Invoke()函数,这个函数内部再调用一个BeginInvoke()函数,这个函数有个神奇的地方就是改变函数的context,即把函数的this指向caller,好咯,现在通过这个调用,委托就顺利地丢给Dispatcher进行管理了,基本没有刚才过程函数什么事了,DO就是在这个时候在BeginInvoke()内部被构造的,就相当于将原来的委托转化为Dispatchre看得舒服的类型,加上个优先级啊,事件触发器啊之类,说到优先级,不愧是过程函数,优先级都是最高的send,基本不用在Queue中排队等候,在进入Dispatcher的接管后这个委托就马上被执行了。

所以从结果上,窗体消息循环如果从过程函数这一层来看是没有什么时间上区别的,但别忘了wpf的do还有其他的优先级,这些优先级就没这么幸运了,尤其像真么background级别的,肯定要老老实实得排队。

在进一步介绍前,先引出在Dispatcher背后还藏着一个羞涩的window对象,这个window跟我们所熟知的window并没有什么区别,只是没有ui界面而已,win32的消息循环它还是挺健全的,Dispatcher还有一个hook的技能我们值得留意,当有新的do进入队列时,就会给隐藏的消息队列发送一个DispatcherProcessQueue的自定义的win消息,这个消息基本是属于自抛自接类型,不过还是得遵守先来后到,到win32消息队列中排排队,等轮到这个消息时,即这个消息被deQueue时,Dispatcher再把这个DispatcherProcessQueue消息hook出来,hook如你所见就是个从消息循环中钩出自己想要消息的钩子,等到这个DispatcherProcessQueue消息被hook出来后,doQueue就会从队列中取出一个do然后执行里面的委托,当然执行的顺序还是要考虑优先级的,到这里我们的委托就成功地被执行啦。

现在来说我们用户来使用Dispatcher,其实我们来得更直接,直接找到我们线程的Dispatcher,然后直接调用BeginInvoke()函数就可以,当然这个函数的两个参数分别是我们do的优先级(这个使我们用户说了算),还有委托,一般用一个Action委托就可以了,然后我们任务就坐等被系统完成了,

上个图好像让大家看得更清楚

上面就是这个过程的一个简略过程图,其实说复杂也不算太复杂吧,

再说为何wpf要搞个Dispatcher吧,很重要的一点就是为了保证线程安全,比如我在ui线程创建了一个element,这个对象就保存在ui线程自己的TLS中,别人家的线程是没有权限看到的,所以Dispatcher就提供了一种安全的跨线程通信的手段,在访问它请求新一轮的查找时是会触发比较严密的安全检查的,另外,Dispatcher提供了我们更为友好的接口支持,Windows编程中,在窗口消息循环中加入Hook是常见的需求,Dispatcher提供了DispatcherHooks类,以Event的形式对外提供了OperationAborted,OperationCompleted,OperationPosted等事件。

从ui操作的角度上来说,Dispatcher有效的保障了ui线程与其他线程的隔离,每一个ui对象都是继承自element类,基类都是DispatchObject,这个类把Dispatcher以属性的形式暴露,给跨线程调用ui控件提供接口,最后告诉大家,wpf中负责界面显示的有两个线程,一个叫做Render线程,负责从visual tree中绘图,实质对ui进行管理的还是隐藏在背后的ui线程,至于wpf的visual tree以及渲染过程,我会在另一篇文章介绍,ok,感谢阅读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值