Здравствуйте, Аркадий!
Вот ваша функция генерации событий:
template <class T> HRESULT
TEvents_UpTask<T>::Fire_OnListenStart(void)
{
DWORD dw;
T * pT = (T*)this;
pT->Lock();
IUnknown ** pp = m_vec.begin();
while (pp < m_vec.end())
{
if (*pp != NULL)
{
dw = (DWORD)pp;
IDispatch* dp;
HRESULT hr = gp_GIT->GetInterfaceFromGlobal(m_GitPointers[dw], IID_IDispatch, (void**)&dp);
if (SUCCEEDED(hr))
{
IUpTaskEvents* Event;
hr = dp->QueryInterface(DIID_IUpTaskEvents, (void**)&Event);
if (SUCCEEDED(hr))
{
Event->OnListenStart();
}
}
}
pp++;
}
pT->Unlock();
}
Я сравнил ее с моей, которая сейчас работает.
Попробуйте удалить строки, стоящие после получения интерфейса из GIT:
if (SUCCEEDED(hr))
{
IUpTaskEvents* Event;
hr = dp->QueryInterface(DIID_IUpTaskEvents, (void**)&Event);
if (SUCCEEDED(hr))
{
Event->OnListenStart();
}
}
Т. е. я не запрашиваю у интерфейса, полученного из GIT конкретный disp-интерфейс, а использую интерфейс IDispatch напрямую.
Вот моя реализация:
Функция вызывается при старте и остановке потока.
bool EventManager::InitDone(bool fInitDone)
{
HRESULT hr;
if (fInitDone)
{
hr = CoInitialize(NULL);
// Получаем интерфейс событий
DWORD cookie = m_connectionPoint->cookie();
m_eventSink = getEventSink(cookie);
m_IsStoped = false;
}
else
{
CoUninitialize();
m_IsStoped = true;
}
return true;
}
Функция, получающая Event Sink из GIT.
ml::com::com_ptr<IDispatch, IID_IDispatch> EventManager::getEventSink(DWORD cookie)
{
HRESULT hr;
ml::com::com_ptr<IDispatch, IID_IDispatch> eventSink;
ml::com::com_ptr<IGlobalInterfaceTable, IID_IGlobalInterfaceTable> GIT;
hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL,
CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (void **)&GIT);
ML_ASSERT( SUCCEEDED(hr) );
hr = GIT->GetInterfaceFromGlobal(cookie, IID_IDispatch,
reinterpret_cast<void **>(&eventSink));
ML_ASSERT( SUCCEEDED(hr) );
return eventSink;
}
Функция потока, вызывается периодически потоком, генерирует события.
void EventManager::Routine()
{
HRESULT hr = E_FAIL;
tstring name;
vector<ml::com::Variant> args;
DISPID dispid;
// Блокировка потока, если список стал пустым
if ( m_eventList.empty() )
{
mutex::scoped_lock lock(monitor);
m_NewEvent.wait(lock);
}
// Берем новое событие из очереди
if ( !ExtractEvent(name, args) )
return;
// Готовим для него все необходимое
BStr memberName( TtoW::from(name).c_str() );
DispParams dp(args);
hr = m_typeInfo->GetIDsOfNames( memberName, 1, &dispid);
ML_ASSERT( SUCCEEDED(hr) );
// Вызываем.
hr = m_eventSink->Invoke(dispid, IID_NULL,
GetUserDefaultLCID(), DISPATCH_METHOD,
dp.get(), NULL, NULL, NULL);
ML_ASSERT( SUCCEEDED(hr) );
}
Т. е. у меня поток в начальный момент времени при старте получает Event Sink, сохраняет его в переменной внутри класса, при этом полученный интерфейс Event Sink'а используется напрямую.