CoRegisterClassObject打破了线程安全性

时间:2013-07-12 22:13:22

标签: c++ com apartments

我正在测试一个将使用coregisterclassobject注册的自定义类工厂,我注意到它会导致线程问题。

我创建了一个测试com对象并创建了它的一个实例,所有内容都按预期运行。它是一个inproc服务器,在注册表中,它的ThreadingModel是“Apartment”。如果我用apartment_threaded调用CoInitializeEx,它会在同一个线程上创建对象,如果我用COINIT_MULTITHREADED调用它,它会在一个单独的线程上创建它(因为它不能在多线程单元中创建)。

但是,如果我首先创建自定义类工厂的实例并使用coregisterclassobject注册它,则该对象始终在同一个线程上创建,即使线程模型与线程的公寓不匹配也是如此。我认为使用coregisterclassobject不会改变线程在多线程单元中的事实,并且对象只能在单线程单元中。

CoInitializeEx(NULL, COINIT_MULTITHREADED);
//CustomClassFactory *factory = new CustomClassFactory();
DWORD regNum = 0;
CLSID clsid = __uuidof(TestComObjLib::TestComObjCoClass);
//CoRegisterClassObject(clsid, factory, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &regNum);
{
   TestComObjLib::ITestComObjPtr ptr;
   HRESULT hr = ptr.CreateInstance(clsid, NULL);
   if(ptr){
      auto str = ptr->HelloWorld();
      cout << str << endl;
   }
}
//CoRevokeClassObject(regNum);
CoUninitialize();

上面按预期生成新线程,但如果我取消注释注释行,COM不会创建任何新线程。我的班级工厂没有做任何奇怪的事情。它只是加载dll directyl并调用DllGetClassObject来获取com定义的类工厂并在其上调用createinstance。对HelloWorld的调用仍然有效,但我不确定为什么线程不符合我的预期。

1 个答案:

答案 0 :(得分:3)

当您使用CoRegisterClassObject显式注册类工厂时,您完全绕过了注册表。即使在注册表中没有提到该对象,它仍然可以工作。

由于从未咨询过注册表,因此指定的线程模型无关紧要。您的对象被认为住在称为CoRegisterClassObject的公寓中(或者确切地说,IClassFactory::CreateInstance将从该公寓调用;类工厂可能会玩弄技巧以使其对象实际在不同的公寓中创建,然后编组回调用者。)