触发一个COM事件从另一个线程(Firing a COM Event From Another Th

2019-09-02 06:56发布

我已创建使用ATL一个进程内COM对象(DLL)。 请注意,这是一个对象,而不是控制(所以没有窗户或用户界面。)我的问题是,我想从第二个线程触发一个事件,我得到一个“灾难性的失败”(0x8000FFFF)。 如果我从我的主线程触发事件,那么我没有得到这个错误。 第二个线程正在调用CoInitializeEx但是这并没有区别。 我现在用的是公寓线程模型,但切换到自由线程没有帮助。

我试图从第二个线程做这个事实显然是至关重要的。 有一个简单的办法做到这一点还是我将不得不通过实施消息的一些隐藏的窗口形式?

举例来说,在我的主要对象的源文件:

STDMETHODIMP MyObject::SomeMethod(...)
{
  CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
  // Succeeds with S_OK
  FireEvent(L"Hello, world!");
  return S_OK;
}

DWORD WINAPI ThreadProc(LPVOID param)
{
  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  MyObject* comObject = reinterpret_cast<MyObject*>(param);
  // Fails with 0x8000FFFF
  comObject->FireEvent(L"Hello, world!");
}

void MyObject::FireEvent(BSTR str)
{
  ...
  // Returns 0x8000FFFF if called from ThreadProc
  // Returns S_OK if called from SomeMethod
  pConnection->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL, NULL);
}

Answer 1:

COM基础知识

在STA你的对象住在一个单独的线程(线程)。 这线程是它创建的一个,它的方法是在执行和它的事件是火。 该STA可以确保你的对象的任何两种方法同时进行(因为它们必须在线程执行的,所以这是一个很好的结果)。

这并不意味着你的对象不能从其他线程访问。 这是比线程其他每个线程创建对象的代理完成。 在螺纹你包与一个IUnknown CoMarshalInterThreadInterfaceInStream和你解开其他线程CoGetInterfaceAndReleaseStream对实际上创建了另一个线程上的代理。 该代理使用消息泵同步调用你反对,那是在线程执行的还是通话,所以线程必须是免费的(不繁忙),以执行从另一个线程调用。

在你的情况,你希望你的对象能够在一个线程中执行的方法和上升的另一个线程事件。 因此,这 MTA发生,所以你的对象有住在MTA,所以你的类必须是自由线程。 线程属于正好一个公寓,所以线程不能在MTA和STA同时进行。 如果你的对象居住在MTA每当STA对象尝试使用它,它会创建一个代理。 所以,你得到一个轻微的负担。

我的猜测是,你正在考虑一些非常聪明的“技术”来卸载你的主线程,并做一些“异步”事件,将不会在年底:-)飞)如果你想想看,必须有一个监听器在这第二个[工人] ...线程

顺便说一句,这条线

MyObject* comObject = reinterpret_cast<MyObject*>(param);

只能在MTA来完成。



Answer 2:

我认为,真正的问题不是你的组件配置,但主机的过程。 许多主机,像Office对象模型的人,住在这种情况下,不允许从什么,但主线程调用它们单线程公寓。
如果是这样的话,你可以让COM做使用单线程公寓模型和一个伴生类移动到一个函数的实际调用并调用从线程功能的工作。
是仅通过幕后的窗口消息为好,但备件你从这个实现自己。

在COM线程 (维基百科):
单线程公寓(STA)模型是一个很常用的模型。 在这里,一个COM对象矗立在类似于桌面应用程序的用户界面的位置。 在一个STA模型中,单个线程专用于驱动对象的方法,即,一个线程被始终用来执行对象的方法。 在这种布置中,方法调用从公寓的外螺纹编组并且由系统(通过一个标准的Windows消息队列)自动排队。 因此,没有关于竞争条件或缺乏同步性的担心,因为另一个调用之前为对象的每个方法调用始终执行完成。

参见信息抽在同一文章。



文章来源: Firing a COM Event From Another Thread
标签: c++ com atl