我正在为一个软件编写插件。该软件调用
void Init() {...}
加载并具有多线程功能:程序可以运行多个线程,可以同时从我的插件调用自定义函数。
在我的插件中,我正在使用COM对象,我按照以下方式初始化:
void Init() { // "Global" initializaton
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
position.CreateInstance(__uuidof(Position));
order.CreateInstance(__uuidof(Order));
}
接下来我实现了基于插件的功能(例子):
int SendOrder(....) {
return order.SendOrder(...); // invoke COM object's method
}
问题是这个变种没有按预期工作,所以我将COM对象实例化直接移动到函数体:
int SendOrder(....) {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
order.CreateInstance(__uuidof(Order));
int ret = order.SendOrder(...);
CoUnitialize();
return ret;
}
现在COM对象将在每个函数调用上实例化,并且此变体按预期工作(每个线程现在都有它自己的公寓和对象的实例),但我担心这不是最好的解决方案,因为实例化是昂贵的操作。
这可以以某种方式更好地完成吗?
答案 0 :(得分:1)
如果您希望能够在多个线程上同时调用COM对象,则应该初始化线程以使用多线程单元而不是单线程单元。
目前,您正在将线程初始化为单线程单元,这意味着在该线程上创建的任何对象将仅在该线程上执行其功能。如果您尝试从其他线程使用其中一个对象,则调用封送到创建它们的线程。
如果COM需要编组一个函数调用另一个线程,它会通过Windows的消息传递系统来完成。如果线程没有泵送它的消息,则永远不会调用该函数;这很可能是你发生的事情,以及为什么你看到没有任何事情被执行。
如果在调用COINIT_MULTITHREADED
时使用COINIT_APARTMENTTHREADED
而不是CoInitializeEx
将线程初始化为多线程公寓,则会允许此线程创建的对象(即您的{{ 1}})用于任何其他线程。