PS:本文中所有线程均使用CoInitialize(NULL)进行COM初始化。跨套间如何使用ActiveX控件?COM跨套间使用时需要列集和散集(书上都是这么说的),但是不知道如何操作。比如像使用ADO访问数据库(通过import导入msado15.dll,形成了IConnectionPtr智能指针)。
在主线程中定义了一个IConnectionPtr的变量m_conn,访问属性设为public,并CreateInstance然后连接数据库。
然后创建工作线程,在工作线程中直接通过((CMain*)AfxGetMainWnd())->m_conn来使用此数据库连接(使用了很长时间),没有出现过错误,为何?更棘手的问题:
在基于对话框的应用程序的主对话框(肯定是主线程喽)上通过右键菜单中的“插入ActiveX控件”,插入了一个ActiveX控件在主对话框上。然后通过类向导为该ActiveX控件关联到一个成员变量,例如将一个MSComm控件关联到m_comm。
然后创建工作线程,将主对话框的指针当作线程参数传递到工作线程,在工作线程中直接通过此参数来访问其m_comm变量来使用MSComm控件,也是正常的。
这种方法有问题吗?如果有问题的话,正确的方法应该怎么操作?
在主线程中定义了一个IConnectionPtr的变量m_conn,访问属性设为public,并CreateInstance然后连接数据库。
然后创建工作线程,在工作线程中直接通过((CMain*)AfxGetMainWnd())->m_conn来使用此数据库连接(使用了很长时间),没有出现过错误,为何?更棘手的问题:
在基于对话框的应用程序的主对话框(肯定是主线程喽)上通过右键菜单中的“插入ActiveX控件”,插入了一个ActiveX控件在主对话框上。然后通过类向导为该ActiveX控件关联到一个成员变量,例如将一个MSComm控件关联到m_comm。
然后创建工作线程,将主对话框的指针当作线程参数传递到工作线程,在工作线程中直接通过此参数来访问其m_comm变量来使用MSComm控件,也是正常的。
这种方法有问题吗?如果有问题的话,正确的方法应该怎么操作?
对于只支持apartment的组件,它内部并未进行同步控制,直接跨线程调用会产生不可预知的后果,尤其是组件方法中需要传递其他接口指针时几乎百分百出错。
如果一个组件支持free或both,那么它的方法里需要传递的其他组件也必须实现成free或both类型,否则就失去了free的意义。
您说的这些我倒是明白。我不明白的地方:
类似于MSCOMM控件,既然是一个ActiveX控件,那么它一定是Apartment的,不可能是Free或者Both。我是使用IDE的右键菜单中的“插入ActiveX控件...”将MSCOMM插入到主对话框(程序基于对话框,MFC)上的。
然后我需要在工作线程中使用此控件,应该怎么办?
1、通过CoMarshalInterThreadInterfaceIntoStream和CoGetInterfaceAndReleasStream?如果可行的话,是否工作线程对MSCOMM控件调用的所有方法实际上都是在主线程中执行的?如果MSCOMM有一个方法是一个长时间的操作,那是不是会引起主线程界面无响应?
2、直接在工作线程中创建MSCOMM控件的实例。对于MFC程序,是否需要在每一个工作线程中调用AfxEnableControlContainer函数?还是只需要在APP类中调用此函数?还是有其它的解决方法?
然后我需要在工作线程中使用此控件,应该怎么办?
1、通过CoMarshalInterThreadInterfaceIntoStream和CoGetInterfaceAndReleasStream?如果可行的话,是否工作线程对MSCOMM控件调用的所有方法实际上都是在主线程中执行的?如果MSCOMM有一个方法是一个长时间的操作,那是不是会引起主线程界面无响应?
2、直接在工作线程中创建MSCOMM控件的实例。对于MFC程序,是否需要在每一个工作线程中调用AfxEnableControlContainer函数?还是只需要在APP类中调用此函数?还是有其它的解决方法?期待对第一个问题的更肯定的答复以及第二个问题的回答。
2、一个组件如果设计得好,每个方法调用都不会占用很长时间,如果真的有耗时操作,应该在组件内部实现多线程,然后使用连接点的方式通知客户端操作状态和结果。
另外,不要被ActiveX这个词给迷惑了,老实说MFC中用ActiveX这个词就不对,_ConnectionPtr和mscomm组件都是普通的组件,即创建即用,真正的ActiveX组件是必须存活在容器中的。