1

我正在为一个软件编写插件。该软件调用

 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 对象将在每个函数调用上被实例化,并且这个变体按预期工作(每个线程现在都有它自己的单元和对象的实例),但恐怕这不是最好的解决方案,因为实例化是昂贵的操作。

这可以做得更好吗?

4

1 回答 1

1

如果您希望能够在多个线程上同时调用 COM 对象,您应该初始化线程以使用多线程单元,而不是单线程单元。

目前,您将线程初始化为单线程单元,这意味着在该线程上创建的任何对象都只会在该线程上执行它们的功能。如果您尝试使用来自不同线程的这些对象之一,调用将被编组到创建它们的线程。

如果 COM 需要将函数调用编组到另一个线程,它会通过 Windows 的消息传递系统来完成。如果线程没有发送它的消息,则永远不会调用该函数;这很可能是发生在您身上的事情,以及为什么您看到没有执行任何操作。

COINIT_MULTITHREADED如果您通过使用而不是COINIT_APARTMENTTHREADED在调用时将线程初始化为多线程单元CoInitializeEx,它将允许该线程(即您的order)创建的对象在任何其他线程上使用。

于 2013-10-26T21:55:30.920 回答