CoRegisterClassObject를 사용하여 com 객체가있는 dll을로드하는 방식을 사용자 정의하려고합니다. 스레드의 아파트 유형이 com 객체와 일치하지 않을 때 발생하는 문제를 해결할 수있는 방법을 찾고 있습니다. 기본 개념은 com 개체를 만들 때 coregisterclassoject가 레지스트리를 무시하기 때문에 STA 개체가 STA 스레드에서 만들어지고 MTA 개체에서 만들어 지는지 확인해야합니다. 다음은 내가 예상 한대로 항상 행동하지는 않는 개념 증명으로 쓴 샘플입니다.Com 정렬 된 공장과 일치하지 않는 스레딩/아파트 동작
LPSTREAM factory_stream = NULL; //GLOBAL VARIABLE FOR TEST
DWORD __stdcall FactoryThread(LPVOID param)
{
CoInitialize(NULL);
//CoInitializeEx(NULL, COINIT_MULTITHREADED);
cout << GetCurrentThreadId(); //THREAD_ID_2
CustomClassFactory *factory = new CustomClassFactory();
factory->AddRef();
CoMarshalInterThreadInterfaceInStream(IID_IClassFactory, (IClassFactory*)factory, &factory_stream);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
factory->Release();
CoUninitialize();
return 0;
}
다음은 내 주요 기능과 관련된 부분입니다.
//CoInitialize(NULL);
CoInitializeEx(NULL, COINIT_MULTITHREADED);
cout << GetCurrentThreadId(); //THREAD_ID_1
HANDLE regThread = CreateThread(NULL, 0, FactoryThread, NULL, 0, NULL);
Sleep(5000); //ensures that the factory is registered
IClassFactory *factory = NULL;
CoGetInterfaceAndReleaseStream(factory_stream, IID_IClassFactory, (void**)&factory);
DWORD regNum = 0;
HRESULT res = CoRegisterClassObject(clsid, factory, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, ®Num);
{
TestComObjLib::ITestComObjPtr ptr;
HRESULT hr = ptr.CreateInstance(__uuidof(TestComObjLib::TestComObjCoClass), NULL);
ptr->OutputOwningThreadId(); //THREAD_ID_3 is just from cout << GetCurrentThreadId()
TestComObjLib::ITestComObjPtr ptr2;
HRESULT hr = ptr2.CreateInstance(__uuidof(TestComObjLib::TestComObjCoClass), NULL);
ptr2->OutputOwningThreadId(); //THREAD_ID_4
}
CoRevokeClassObject(regNum);
CoUninitialize();
아이디어는 레지스트리가를 CoRegisterClassObject와 함께 사용하지 않아야하기 때문에, 내가 수동으로 아파트를 그 반대 STA에 스레드 객체 대신 현재 MTA 스레드 등을 만드는 데 필요한 것이 었습니다. CoRegisterClassObject를 사용하지 않을 때 CoGetClassObject는 새 스레드를 생성하고 해당 스레드에서 DllGetClassObject를 호출하므로 STA에서 클래스 팩토리를 생성해야만 객체가 생성된다는 사실을 알게되었습니다.
위의 예에서 볼 수있는 문제는 스레드 ID가 항상 예상대로 끝나지 않는다는 것입니다. FactoryThread가 아파트 스레드로 초기화되고 주 스레드가 다중 스레드로 초기화 된 경우 THREAD_ID_2 == THREAD_ID_3 == THREAD_ID_4! = THREAD_ID_1 (예상되는대로 공장이 이러한 객체를 생성하며 팩토리의 스레드에있을 수 있음). 그 스레딩 모델은 thread_id_3 == thread_id_4하지만 전환 있지만 COM 개체가 스레드에서 생성 될 수 있지만, thread_id_2 및 thread_id_1 다른 경우 2.
이 일치하지 않는 것, 그리고 상황에서 원치 않는 동작이 발생할 수 있습니다 다른 스레드가 관련되어 있습니다. 레지스트리에만 의존하고 coregisterclassobject를 사용하지 않는 경우 STA에서 자유 스레드 객체를 만든 경우 객체가 MTA에있는 com에 의해 생성 된 다른 스레드에 만들어집니다. 그러면 세 번째 스레드가 생성됩니다. 또한 STA에 있었기 때문에 객체를 생성 할 때 새로운 MTA 스레드가 아닌 최초의 MTA 스레드에 객체를 넣을 수있었습니다 (객체의 threadingmodel과 스레드의 아파트 유형이 반대로 된 경우에도 마찬가지입니다). 그러나 coregisterclassobject를 사용하여 위와 같은 자체 공장을 만들고 개체가 다중 스레드되었지만 STA에 스레드가있는 경우 이러한 다중 스레드 개체를 만든 각 새 스레드가 새 MTA 스레드를 생성하므로 낭비적이고 일관성이 없습니다. 정상적으로 일어나는 일.
알 수 있습니다. COM이 STA 및 MTA 스레드와 다르게 통신한다는 사실을 깨닫지 못했습니다. 당신의 도움을 주셔서 감사합니다. – bdwain