描述:
组件中创建了线程,在线程函数中调用FireEvent客户程序中收到事件通知时会引起崩溃,请那位大侠支着,谢谢
解决方案1:
有:
这是lop5712(LOP)的回答,我转贴给你。
那是因为FireEvent实际上是调用客户端实现的一个接口(在这就是IE实现的IDispatch接口)的方法,而ActiveX控件一定是放在STA套间(虽然也可以,但应该没人实现为放在MTA)的,因此工作线程调用IE的IDispatch接口一定且必须是代理接口,这个接口必须通过汇集得到(以创建代理对象)。
即需要在主线程调用CoMarshalInterface来列集IE的那个IDispatch接口,再在工作线程调用CoUnmarshalInterface来散集IDispatch接口,进而在工作线程中通过散集的IDispatch接口发起事件。由于楼主是在线程间汇集接口,所以可以使用CoMarshalInterThreadInterfaceInStream和CoGetInterfaceAndReleaseStream代替上面的两个函数进行汇集,效率会有所提高。
而这样做(即建立代理对象)的实际工作工程,与楼主说的“另外”是异曲同工的,所以楼主要是闲上面麻烦,可以按照楼主说的“另外”来实现。
还有就是COleControl是MFC的包装类,其中使用了一些MFC的底层的机制(如线程状态等),所以当欲跨线程传递ActiveX对象的指针时,不可直接传递COleControl*之类,否则就有可能发生断言失败,而应该通过FromHandle和Detach来传递句柄(不过这样就不能使用派生类的相关成员函数)。因此楼主如果想使用上面的方法,需先获得客户的接口指针(即IDispatch),然后将其列集得到的IStream*作为线程参数传递给工作线程,而不要使用直接的this。
详见:
http://expert.csdn.net/Expert/topic/2650/2650433.xml?temp=.8801386
很简单,在控件内部公开一个方法,客户端用这个方法把自己的窗口句柄或者主线程ID告诉控件,然后控件就可以截获消息了
解决方案3: 不要在内部创建的线程调用FireEvent,postmessage到ActiveX控件窗口,由那里调用FireEvent
抱歉,没有看前面的代码,但你上面的线程函数不知是不是你省略掉了,在执行几乎全部的COM函数前需要调用CoInitialize( NULL );以进入STA套间(也可使用CoInitializeEx进入MTA,视你的需要)。在退出线程前调用CoUninitialize();
请确保调用了CoInitialize和CoUninitialize
这是VB的限制,他只允许一个主线程运行,如果有其它的线程运行,它会强制终止线程,如果终止失败,VB就会“当掉”。
你必须在主线程中激发事件,你在工作线程中投递一个消息到主线程中,然后再激发事件,但你最好不要用窗口类的指针,应该用窗口句柄发送,就像这样::PostMessag(hWndDlg,...);