Re: CoMarshalInterThreadInterfaceInStream FinalRelease not called

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



You need to marshal the ougoing interface, not an interface back
to your own object (though I clearly can see how that can get
abused...). See the following COM FAQ for other alternatives:

http://vcfaq.mvps.org/com/1.htm

Also you may find this FAQ article useful:

http://vcfaq.mvps.org/com/11.htm

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@xxxxxxxx
MVP VC FAQ: http://vcfaq.mvps.org
=====================================

"Phil Riera" <PhilRiera@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:A5C0D3D0-8862-4AD3-9E8B-9FF8D200DF1B@xxxxxxxxxxxxxxxx
Thank you for the clarification. I didn't mention that I am doing this so
that I can fire an event from the main object's thread for compatibility
reasons. Thank you for your assistance.

"Alexander Nickolov" wrote:

Means don't marshal an interface pointer to your object into
your thread. Then the whole mess will be neatly solved. Don't
call the API in the title - you marshal a pointer to yourself.
Make your thread COM-agnostic. Not sure how to put it
in clearer terms...

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@xxxxxxxx
MVP VC FAQ: http://vcfaq.mvps.org
=====================================

"Phil Riera" <PhilRiera@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:094D211D-4E2E-4110-BDB3-273D603F43AB@xxxxxxxxxxxxxxxx

Thank you Alexander.
As you suggested, I moved the set event into another function called by
the
client. I am a little confused however about what you mean by using a
C++
class pointer to decouple my thread from COM. Can you elaborate?

"Alexander Nickolov" wrote:

Your thread seems to be wating on an event that is triggered
from within your FinalRelease. Since the thread itself holds
a reference to your object, this would never execute. You need
an external party to tell your thread to stop. This in turn will
cause it to release its reference on your obect and FinalRelease
will execute. Since this will happen on the thread itself, you
shouldn't wait for the thread to finish (clear deadlock). However,
once the object is destroyed, your thread may not touch any
object state (the engine pointer) since that is no longer valid
(your code is ok in that regard right now). This is quite tangled
IMHO. I suggest you decouple your thread from COM and
have it use an internal C++ class pointer only and no self-
reference count bump. Then it'll be your client releasing an
interface pointer to the object that causes your destruction
sequence, not your internal event.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@xxxxxxxx
MVP VC FAQ: http://vcfaq.mvps.org
=====================================

"Phil Riera" <Phil Riera@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:2AC1DA39-CB45-4D9F-B825-2B3291A98727@xxxxxxxxxxxxxxxx
I've created an object that marshals an interface with
CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream.
The
interface pointer is working as intended but my FinalRelease is not
being
called. Here is a sample of what I am doing.


unsigned __stdcall CEngineObj::AnalysisThreadProc( void* args )
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
CEngineObj* engine = static_cast<CEngineObj*>(args);
DWORD dwResult;
HRESULT hr = S_OK;

// unmarshal interface pointer
IInternalEngineCallback* pCallback;
hr = CoGetInterfaceAndReleaseStream (*(engine->m_ppStream),
IID_IInternalEngineCallback,
(void**) &pCallback);
delete engine->m_ppStream;
engine->m_ppStream = NULL;

while(true)
{
dwResult = WaitForMultipleObjects( engine->NUM_EVENTS,
engine->m_hEvents,
FALSE, INFINITE );
switch( dwResult )
{
case WAIT_OBJECT_0 + EVTEXIT:
pCallback->Release();
_endthreadex(0);
return 0;
}
}

CoUninitialize();
return 0;
}

HRESULT CEngineObj::FinalConstruct()
{
HRESULT hr = S_OK;

// Marshal interface pointer
m_ppStream = new IStream*;
hr =
::CoMarshalInterThreadInterfaceInStream(IID_IInternalEngineCallback,
reinterpret_cast<IInternalEngineCallback*>(this), m_ppStream);
if (FAILED (hr)) {
delete m_ppStream;
m_ppStream = NULL;
return hr;
}

// Create the thread
unsigned threadID;
m_hAnalysisThread = (HANDLE)_beginthreadex( NULL, 0,
&AnalysisThreadProc,
this, 0, &threadID );
if( 0 == m_hAnalysisThread )
return E_FAIL;

return hr;
}

void CEngineObj::FinalRelease()
{
if( m_hAnalysisThread && m_hEvents[EVTEXIT] )
{
SetEvent(m_hEvents[EVTEXIT]);
WaitForSingleObject( m_hAnalysisThread, INFINITE );
CloseHandle(m_hAnalysisThread);
}
}


Any help would be greatly appreciated.








.



Relevant Pages

  • Re: Pointer Marshalling quesiton
    ... involves interface pointer marshling. ... Microsoft MVP, MCSD ... "Alexander Nickolov" wrote: ...
    (microsoft.public.win32.programmer.ole)
  • Re: How to pass COM object created in one EXE into another EXE, an
    ... You need to store a single pointer to C somewhere within A ... Alexander Nickolov ... > I did not do any interface marshal for DLL_C, ... >> Microsoft MVP, MCSD ...
    (microsoft.public.vc.atl)
  • Re: Getting the interface pointer for current object
    ... "Alexander Nickolov" wrote in message ... Note the returned interface pointer is _not_ ... > Microsoft MVP, MCSD ... >> How do you get an interface pointer for the current class object your are ...
    (microsoft.public.vc.atl)
  • Re: ATL OLE DB and SQL Server
    ... > "Alexander Nickolov" wrote in message ... > from that BLOB - the interface might be garbage - you need to ... > hold multiple BLOBs open too, so if you have multiple BLOBs in ... > Microsoft MVP, MCSD ...
    (microsoft.public.vc.atl)
  • Re: CreateNPPInterface
    ... Microsoft MVP, MCSD ... Command-line app, and I neglected to ad all the COM automation headers, ... "Alexander Nickolov" wrote: ... Now the GUI dialog for selecting a network interface works ...
    (microsoft.public.win32.programmer.networks)