您的位置:首页 > 其它

用Windows消息机制解决跨线程添加子控件异常

2010-09-20 12:59 513 查看
写过Winform程序的同学或许都遇到过这样的异常:

Title
在某个线程上创建的控件不能成为在另一个线程上创建的控件的父级

遇到这个问题之后,第一反应当然是g一把,解决方案大多数都是类似这样的代码:

1 if(XXX.InvokeRequired)
2 {
3 //...
4 }
5 else
6 {
7 //...
8 }

这段代码的原理是将

1 ControlCollection.Add(Control);
转移到主线程中执行,貌似能解决哦?但是很多情况下并不能解决根本问题,异常照样会抛出来,具体原因我也不得而知,但是至少我们从可以绕道而行之...

上文提到在主线程中添加子控件的原理,那么我们可以从此下手,很显然,windows消息的触发一定是在主线程中执行的,在尝试之后我总结了2种情况:

1.简单子控件

如果只需要添加个按钮啥的,可以直接利用父控件的Paint消息,因为很简单,要注意的是Paint消息会不定时触发,需避免重复添加子控件

2.复杂子控件

如果子控件中包含各种COM控件,而且还包含耗时的业务调用,这时就得小心了,如果继续在Paint消息中处理,很可能会导致界面刷新不及时,而且这种方式确实有点山寨...

那具体要怎样做呢?

调用Windows API之PostMessage(Intptr, int, int, int)向某窗口发送消息,当然SendMessage亦可
一般情况下,该窗口对象可以重写WndProc方法分发该消息,但是还有更优雅的方式:继承IMessageFilter接口,拦截所有的Windows消息进行分发
处理类对象接收到对应的windows消息后创建子控件对象后添加

OK,总结吧

优点:很显然,无需担心COM控件的创建以及方法调用,实乃居家旅行杀人越货之良品
缺点:需要创建诸多的类成员变量(不优雅),以及需要仔细控制方法调用顺序,更可能需要对已有的代码结构进行仔细的重构,很好很山寨...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: