Question

I'm testing out a custom class factory that will be registered using coregisterclassobject, and I'm noticing that it causes threading problems.

I created a test com object and created an instance of it, and everything behaved as expected. It's an inproc server, and in the registry, its ThreadingModel is "Apartment". If I call CoInitializeEx with apartment_threaded, it creates the object on the same thread, and if I call it with COINIT_MULTITHREADED, it creates it on a separate thread as it should (since it can't be created in the multithreaded apartment).

However, if I create an instance of my custom class factory first and register it with coregisterclassobject, the object is always created on the same thread, even if the threading model doesn't match the thread's apartment. I thought that using coregisterclassobject wouldn't change the fact that the thread is in the multi-threaded apartment and the object can only be in a single-threaded apartment.

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();

The above spawns new threads as expected, but if I uncomment the commented lines, COM doesn't create any new threads. My class factory doesn't do anything weird. It just loads the dll directyl and calls DllGetClassObject to get the class factory that com defined and calls createinstance on that. The call to HelloWorld still works, but I'm just not sure why the threading is not what I expected.

Was it helpful?

Solution

When you register the class factory explicitly with CoRegisterClassObject, you bypass the registry entirely. It would still work even if the object isn't mentioned in the registry at all.

Since the registry is never consulted, the threading model specified there is irrelevant. Your object is considered to live in the apartment that called CoRegisterClassObject (or to be precise, IClassFactory::CreateInstance would be called from that apartment; the class factory may play tricks to get its object actually created in a different apartment, then marshalled back to the caller).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top