FTM или Специальный маршалинг
От: Kolex Россия  
Дата: 22.06.03 09:21
Оценка:
Hi, all!

Есть приложение, которое работает в основном потоке проинициализированном через OleInitialize(NULL). (Если процесс проинициализировать через CoInitializeEx(NULL, COINIT_MULTITHREADED), то проблем не будет вообще никаких, но мне так нельзя).
В этом же процессе создается поток, проинициализированный через CoInitializeEx(NULL, COINIT_MULTITHREADED). В потоке выполняется код из dll-библиотеки.

Далее во втором потоке мне необходимо создать COM-объект (потоковая модель Both) через CoCreateInstance, реализованный в основном приложении и использующий FTM (без прокси), так как дальнейшие вызовы методов этого объекта должны выполняться во втором потоке:

class ATL_NO_VTABLE IFormSupportImpl :
public IDispatchImpl<IFormSupport, &IID_IFormSupport, &LIBID_ModSystemForms>,
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<IFormSupportImpl, &CLSID_FormSupport>
{
public:
DECLARE_REGISTRY_RESOURCEID(IDR_FORMSUPPORT)

public:
IFormSupportImpl(){};
~IFormSupportImpl(){};

public:
BEGIN_COM_MAP(IFormSupportImpl)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IFormSupport)
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
END_COM_MAP()

DECLARE_PROTECT_FINAL_CONSTRUCT()
DECLARE_GET_CONTROLLING_UNKNOWN()

HRESULT FinalConstruct()
{
HRESULT hr = CoCreateFreeThreadedMarshaler(
GetControllingUnknown(), &m_pUnkMarshaler.p);
return hr;
}

void FinalRelease()
{
m_pUnkMarshaler.Release();
}

CComPtr<IUnknown> m_pUnkMarshaler;

public:
// IFormSupport implementation
};

На Win2000 все работает как часы. Но на NT4 6SP все равно создается прокси и вызовы методов COM-объекта выполняются в основном потоке. В чем может быть проблема?

----------------------------------------------------
Для обхода проблемы я попытался реализовать свой маршаллер.

STDMETHODIMP IMarshalImpl::GetUnmarshalClass(...)
{
*pCid = CLSID_FormSupportProxy;
return S_OK;
}

STDMETHODIMP IMarshalImpl::GetMarshalSizeMax(...)
{
*pSize = 0;
return S_OK;
}

STDMETHODIMP IMarshalImpl::MarshalInterface(...)
{
return S_OK;
}

FormSupportProxy реализован также в основном приложении.

После вызова MarshalInterface выполнение возвращается во второй поток в точку вызова CoCreateInstance c ошибкой "Класс не зарегистрирован". FormSupportProxy при этом не создается, в реестре зарегистрирован (потоковая модель Both; регистрировал его как LocalServer32, так и InprocServer32).

Причем, если реализацию прокси вынести в отдельную библиотеку, то прокси успешно создается!

Что же здесь не так?

Заранее спасибо за ответы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.