Ok, your thread management seems to be in order. Apart
I don't see anything wrong with the code.
What thread causes the deadlock, e.g. who holds the lock
Hello Alexander,
The thread is created by the COM object as follows. I don't use Windows
messages inside the Main Thread, the messaging is done via a FIFO stack
using a push/pop mechanism. The messages originate from another thread
that has a longer lifecycle. I use the CComDynamicUnkArray_GIT template
class that was published on the web. Any thoughts would be very much
appreciated.
/*-----------------------------------------------------------------------------
*
* content: The last called function in initilizing com object.
*
* input: none
*
* return: none
*/
HRESULT
CApplicationLayer::FinalConstruct()
{
THREAD_ID threadID;
pAppLayer = this;
Thread_Sem_Init(&thread.semaphore);
// create the thread
thread.m_hThread = CreateThread(
NULL,
0,
&ThreadProc,
reinterpret_cast< void* >(this),
0,
(unsigned long*)&threadID);
//Wait for the thread to signal that it has started
Thread_Sem_Wait(&thread.semaphore);
return S_OK;
}
/*-----------------------------------------------------------------------------
*
* content: The last called function before com object wil be
destroyed.
*
* input: none
*
* return: none
*/
void CApplicationLayer::FinalRelease()
{
DestroyThread();
}
// the thread function
DWORD WINAPI
CApplicationLayer::ThreadProc(LPVOID lpParameter)
{
pApplicationLayer = reinterpret_cast< CApplicationLayer*
(lpParameter);
CoInitializeEx(NULL, COINIT_MULTITHREADED);
do
{
if (!pApplicationLayer->OnInitInstance())
break;
if (!pApplicationLayer->Run())
break;
} while (True);
pApplicationLayer->OnExitInstance();
CoUninitialize();
return 0;
}
void CApplicationLayer::DestroyThread()
{
thread.keep_going = FALSE;
//Wait for it to stop
Thread_Sem_Wait(&thread.semaphore);
Thread_Sem_Destroy(&thread.semaphore);
THREAD_CLOSE_HANDLE(thread.m_hThread);
}
//The Event being fired would look like this :-
HRESULT Fire_Iam(BACnetServiceIam *service)
{
HRESULT hr;
CComVariant varResult;
CComObject<CIam> *Iam;
VARIANT vntArg;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections;
nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
CComQIPtr< IDispatch, &IID_IDispatch > pDispatch( sp.p );
if (pDispatch.p != NULL)
{
VariantClear(&varResult);
//Create a new Iam object
if (hr = CComObject<CIam>::CreateInstance(&Iam))
return hr;
//Set the pointers up
Iam->Iam.iAmDeviceIdentifier = service->iAmDeviceIdentifier;
Iam->Iam.maxAPDULengthAccepted = service->maxAPDULengthAccepted;
Iam->Iam.segmentationSupported = service->segmentationSupported;
Iam->Iam.vendorID = service->vendorID;
::VariantInit(&vntArg);
V_VT(&vntArg) = VT_DISPATCH;
Iam->GetUnknown()->QueryInterface(IID_IIam,
(void**)&vntArg.pdispVal);
DISPPARAMS disp = { &vntArg, NULL, 1, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
Iam->GetUnknown()->Release();
}
}
return varResult.scode;
}
Alexander Nickolov wrote:
Who is responsible for the lifetime of your thread? Is it a
COM object?
--