WPF起步(下) --- WPF的画图请求是如何生成和派发

本文深入探讨了WPF中UI线程与渲染线程如何通过DUCE机制通信,重点分析了如何利用调试器观察`System.Windows.Media.Composition.DUCE+Channel.SendCommand`函数的触发。通过示例展示了改变窗口背景颜色的尝试,揭示了WPF窗口重绘是通过自定义Windows消息触发,并详细展示了从Background改变到Dispatcher队列、Render方法直至DUCE发送请求的整个过程。文章最后提及死循环无法改变背景的原因,并提到了`System.Windows.UIElement.InvalidateArrange()`方法在优化重绘时机中的作用。
摘要由CSDN通过智能技术生成

WPF通过System.Windows.Media.Composition.DUCE相关函数跟worker thread通信,具体来说是通过kernel object来实现的。仔细研究了DUCE内相关函数后,发现这个东西相当有货,从暴露出来的函数名字,就可以猜测到UI thread和render thread的交互模型。应该是UI thread准备好足够的数据后,然后发送请求通知Render thread,然后Render thread拿到对应的请求完成工作。从名字上看,下面这个函数就非常的值得关注:

System.Windows.Media.Composition.DUCE+Channel.SendCommand

接下来的任务就是通过调试器来进一步分析UI thread中具体发生了些什么事情。如果能拿到足够多的callstack sample,这对于通过reflector研究WPF实现是很有帮助的。我的下一个目标是,分析WPF的窗口绘画到底是如何进行的。

观察WPF窗口绘画的简单办法就是写一个死循环,在循环中做一些重画的工作。我这里选择改变窗口背景。我决定用下面的办法来做:
void button2_Click(Object sender, RoutedEventArgs e)
 {
while(true)
{
this.Background=new SolidBrush(...); //red
this.Background=new SolidBrush(...); //black
}
}

很可惜,我发现这个方法不能循环改变窗口背景。我决定换一个方法,在timer里面来做这个事情。在WPF的帮助文档中找到DispatchTimer,成功实现了窗口背景的循环重绘。在窗口死循环绘制的时候,用Windbg断下来,检查System.Windows.Media.Composition.DUCE+Channel.SendCommand函数的触发情况:

0:000> !name2ee PresentationCore.dll!System.Windows.Media.Composition.DUCE+Channel.SendCommand
Module: 53cb8000 (PresentationCore.dll)
Token: 0x060004e2
MethodDesc: 53e2d808
Name: System.Windows.Media.Composition.DUCE+Channel.SendCommand(Byte*, Int32)
JITTED Code Address: 538f61c0
0:000> bp 538f61c0
0:000> g
Breakpoint 0 hit
eax=013c4428 ebx=00000007 ecx=013c4428 edx=0012e888 esi=013c4428 edi=013e6e14
eip=538f61c0 esp=0012e880 ebp=013ff898 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
PresentationCore_ni+0xb61c0:
538f61c0 55              push    ebp
0:000> !clrstack
OS Thread Id: 0xffc (0)
ESP       EIP    
0012e880 538f61c0 System.Windows.Media.Composition.DUCE+Channel.SendCommand(Byte*, Int32)
0012e888 539169f2 System.Windows.Media.Composition.DUCE+CompositionNode.SetContent(ResourceHandle, ResourceHandle, Channel)
0012e89c 538e4f2e System.Windows.UIElement.RenderContent(System.Windows.Media.RenderContext, Boolean)
0012e8b4 538ea5ed System.Windows.Media.Visual.RenderRecursive(System.Windows.Media.RenderContext)
0012e8f8 538eabcf System.Windows.Media.Visual.UpdateChildren(System.Windows.Media.RenderContext, ResourceHandle)
0012e920 538ea652 System.Windows.Media.Visual.RenderRecursive(System.Windows.Media.RenderContext)
0012e964 538ea3ea System.Windows.Media.Visual.Render(System.Windows.Media.RenderContext, UInt32)
0012e980 53914b9a System.Windows.Media.CompositionTarget.Compile(Channel)
0012e994 539121d5 System.Windows.Media.CompositionTarget.System.Windows.Media.ICompositionTarget.Render(Boolean, Channel)
0012e9bc 539119ee System.Windows.Media.MediaContext.Render(System.Windows.Media.IC

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值