cad.net WPF嵌入技术2_将WPF嵌入到Acad08
嵌入WPF
将WPF嵌入到Acad08的时候,vs调试期间能成功,但是直接运行cad就不成功了.这是为什么呢?
调试环境:
这个问题测试版本为Acad2008,在Acad2014已经没有了...中间版本不清楚...
估计net3.5上都有(08,09,10,11,12,13)
问题如下:
利用vs debug调试运行,能看见我设置的小齿轮动起来了.
但是直接运行Acad2008的时候,则小齿轮无法运行,这个界面是卡死的.
原因:
WPF必须新建一个线程来承载UI线程,
然后CAD2008用的是net3.5,这个net版本没有很好地在runtime实现Dispatcher.Run()
//WPF的UI线程(Dispatcher)
所以必须新开一个线程,之后就会占用这个当前线程来作为UI线程.
我实验了一下,
不新建一个线程,直接使用Dispatcher.Run()
会抢夺了Acad的主线程,导致WPF界面会动了,但是Acad则卡死了.
占用UI线程之前必须将WPF控件和嵌入动作包裹在线程内部再开始启动线程,否则会出现跨线程通讯....
跨线程通讯:
但是即使如此,无可避免在WPF线程内的其他地方依然有和Acad跨线程通讯问题,怎么做呢?
见下篇
WPF线程模型
精华摘录一段:
通常,WPF 应用程序从两个线程开始:一个用于处理呈现,一个用于管理 UI;
呈现线程有效地隐藏在后台运行,而 UI 线程则接收输入、处理事件、绘制屏幕以及运行应用程序代码;
UI 线程对一个名为 Dispatcher 的对象内的工作项进行排队; Dispatcher 基于优先级选择工作项,并运行每一个工作项,直到完成;
每个 UI 线程都必须至少有一个 Dispatcher,并且每个 Dispatcher 都只能在一个线程中执行工作项; 这两段是MSDN上关于WPF线程模型的描述;
主要介绍了两个概念:
一,WPF中线程一分为二,一个用于呈现(Render),一个用于管理UI;
二,在UI线程中,使用了一个名为Dispatcher的类帮助UI线程处理任务; 在WPF中,所有的WPF对象都派生自DispatcherObject,DispatcherObject暴露了Dispatcher属性用来取得创建对象线程对应的Dispatcher;
鉴于线程亲缘性,DispatcherObject对象只能被创建它的线程所访问,其他线程修改DispatcherObject需要取得对应的Dispatcher, 调用Invoke或者BeginInvoke来投入任务;
一个UI线程至少有一个Dispatcher来建立消息泵处理任务,一个Dispatcher只能对应一个UI线程;那么UI线程和Render线程又如何呢?
开篇提到,WPF线程一分为二,一个是UI线程,一个是Render线程;
这两个被设计成分离的关系, 通过Channel(event)来进行通信;两者之间的数量关系是一个WPF进程只能有一个Render线程, 旦可以有大于等于一个的UI线程;
通常情况下是一个UI线程,也就是一个Dispatcher,那么什么情况下需要建立多个呢?
大多情况下是不需要的,少数情况下,比如MediaElement,或者Host其他ActiveX控件,我们期望在其他线程中创建, 以提高性能;
可以新建线程,在新线程中创建控件,并调用Dispatcher.Run启动Dispatcher;
这样主Window和新控件就处在不同线程中,两者间的通信可以使用VisualTarget连接视觉树或者使用D3DImage拷贝新控件到主Window中显示