MFC ActiveX控件问题

kyowl 2009-03-12 09:21:26
现在碰到这么个问题,请大家帮忙看看:

一个MFC 单文档程序,其中有COM编程(主要是实现OPC客户端),用的是CoInitialEX(NULL, COINT_MULTITHREAD)初始化
的COM库。应该算是MTA套间吧。现另有一个用MFC开发的ActiveX控件,不知道是STA还是MTA的,估计MFC开发的都是STA的?
在这个单文档程序里无法使用该ActiveX控件(比如,把该控件放在对话框上,程序运行后,该对话框就无法正常弹出了,跟踪发现
调用DoModal函数立即返回了),改成CoInitial(NULL)初始化COM库或者用COINT_APARTMENTTHREAD参数调用CoInitialEX的
话可以正常使用该ActiveX控件。
不知道这是不是所谓的套间的冲突,如果需要使用MFC开发的ActiveX控件,是不是必须用STA线程模型的COM库才行,有没有
办法修改该ActiveX控件,使得在CoinitialEx(NULL, COINT_MULTITHREAD)下可以正常运行? 因为不想盲目改成CoInitial()
来初始化,MSDN上面说不应该用它,应该使用CoInitialEx函数。
...全文
189 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
jameshooo 2009-03-12
  • 打赏
  • 举报
回复
用STA初始化的线程能使用任何套间类型的COM对象,无论这个对象本身是STA还是free的。这个问题其实根本不用去考虑,COM底层库都帮你考虑好了。

STA对速度肯定有影响,但影响非常小,无非就是把操作排队再顺序执行,如果你的线程之间自己做同步,本质上也是一个排队执行的过程,没有区别。
kyowl 2009-03-12
  • 打赏
  • 举报
回复
那请问下,我现在这个情况该如何协调两类COM对象的使用了,有点晕 ◎_◎

本来考虑的方法有:
1. ActiveX 控件想办法支持MTA? 不过貌似被否定了,所有ActiveX控件只可能是STA,没有办法MTA?

2. 在STA环境下使用OPC COM对象(即通过CoInitial()或者AfxOleInit()初始化)。 但是,这样总觉得
是不是会有问题,请帮忙解疑下。因为实际运行时候会有多个线程同时进行OPC通信,即使用该COM对象,
如果是STA的话,是不是指的这样的调用COM对象的请求是排队进行的,我的理解是STA靠这个机制来保证多线程
同时使用COM对象时候的同步问题。那如果对通信速度要求高的情况下,STA模型是不是会对速度有一定的影响。
jameshooo 2009-03-12
  • 打赏
  • 举报
回复
还有,所有的ActiveX控件都是STA的。
jameshooo 2009-03-12
  • 打赏
  • 举报
回复
oyljerry的答案有些问题,一个进程不能混合使用STA和MTA,要么全部都是STA,要么全部都是MTA。

MFC程序不要使用MTA初始化COM,会有很多不良后果,严重的导致整个程序失去响应,原因在于MFC多线程本身非常依赖于TLS功能,使用MTA很容易破坏MFC的TLS数据。
通常使用AfxOleInit()初始化就可以了。
kyowl 2009-03-12
  • 打赏
  • 举报
回复
恩,明白。
但是,还有个问题,如果我的新线程(MTA模型,OPC客户端)要更新该ActiveX控件,是不是没有办法实现了(要用到什么列集、散列之类的?)?只能把数据通信给主线程,让主线程来操作该ActiveX控件?

我在想,是不是最好的办法是让该ActiveX控件支持MTA?不知道能不能把一个MFC开发的ActiveX控件改成MTA的?如果可以,请讲下方法或者给个例子,不胜感激。
oyljerry 2009-03-12
  • 打赏
  • 举报
回复
主线程保持STA,你开新的线程中使用MTA,在这个线程中使用 OPC客户端 ...
kyowl 2009-03-12
  • 打赏
  • 举报
回复
oylijerry兄的意思是:我的主线程不要开MTA,在别的线程里跑我的COM程序。这样就能保持主线程的模型为原来的STA,然后在主线程里使用MFC ActiveX控件就不会有什么问题,是这个意思吧
kyowl 2009-03-12
  • 打赏
  • 举报
回复
现在的情况就是,我的MFC程序是OPC客户端,使用到了COM基础编程,用的模型到MTA,在主线程里(App类下的InitInstance函数下)调用了CoInitialEx(NULL, COINT_MULTITHREAD)。结果OPC COM对象没问题,但是在MFC程序下使用单独开发的ActiveX控件(MFC开发的)时候,就碰到问题了,无法正常使
用了(含ActiveX控件的对话框无法弹出)。
现在想知道如何解决该问题,请大伙帮帮忙。我自己知道如果改成CoInitial()来初始化控件可以正常使用,但是因为OPC客户端是个多线程模型的,我觉得
这样改会出现问题。
oyljerry 2009-03-12
  • 打赏
  • 举报
回复
对于MFC的程序,它默认就会以STA套间初始化,如果你想使用MTA,放到一个线程中使用 CoInitialEx COINIT_MULTITHREADED
levelmouse 2009-03-12
  • 打赏
  • 举报
回复
MFC也可以用AfxOleInit()
levelmouse 2009-03-12
  • 打赏
  • 举报
回复
CoInitialEX(NULL, COINT_MULTITHREAD)

MFC applications must be initialized as single threaded apartment (STA).
If you call CoInitializeEx in your InitInstance override, specify
COINIT_APARTMENTTHREADED (rather than COINIT_MULTITHREADED).
jameshooo 2009-03-12
  • 打赏
  • 举报
回复
没有问题,去做吧。
kyowl 2009-03-12
  • 打赏
  • 举报
回复
谢谢两位的回答。

对这个问题,现在我的理解是:直接用CoInitial()或者AfxOleInit(),能保证我程序里任何一个线程,同时使用多个不同套间类型的COM对象(针对本程序就是一个ActiveX对象和一个OPC COM对象)都没问题是吗,是的话就这么去做了。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧