[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework.sdk

Calling back from COM into C# code through custom interface

Ted Miller

9/13/2003 9:01:00 PM

Hi folks, I originally posted this on
microsoft.public.dotnet.framework.interop. Reposting to broaden the
audience.

I'm having an interop problem where my managed component is reentered from
COM on the wrong thread, at which point things seem to go downhill very
rapidly. I'm successfully making very heavy use of COM interop elsewhere in
my C# code, but I'm having trouble finding a way around this particular
problem. This is VS .Net 2003.

The scenario involves calling an apartment-threaded COM object from managed
code, passing it a pointer to a specific COM interface to be used for
callback notifications. The COM object creates a worker thread and marshals
the callback notification interface pointer into it (via
CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream). The
worker thread calls through the marshaled interface pointer periodically, to
perform various notifications.

In rough pseudo-idl:

[ obect, local, oleautomation,uuid(...) ]
interface ILoaderNotify : IUnknown {
HRESULT __stdcall ReportPercentComplete(...);
}

[ object, local, oleautomation,uuid(...) ]
interface ILoader : IUnknown {
HRESULT __stdcall StartLoad(...,ILoaderNotify *Notify);
}

[ uuid(...) ]
coclass Loader {
[default] interface ILoader;
}

All of this works fine in a VB6 environment. Even though the worker thread
is in the MTA, it has the marshaled pointers to the callback interface, so
calling through it means that the original caller correctly gets the
notifications in its STA.

Implements ILoaderNotify

private sub DoLoad(...)
dim obj as Loader
set obj = new Loader
obj.StartLoad ...,Me
end sub

private sub ILoaderNotify_ReportPercentComplete(...)
' Gets called on the same thread as DoLoad()
end sub

Unforutnately in C#, the callback is getting called directly by the worker
thread.

internal class Loader : ILoaderNotify {

private void DoLoad() {
Loader obj = new Loader();
obj.StartLoad(...,this);
}

void ILoaderNotify.ReportPercentComplete(...) {
//
// This guy is getting called on a different thread than
DoLoad().
// The ApartmentState property indicates MTA.
//
}
}

I am wondering what I am doing wrong -- I'm sure there is something I am
missing but I'm having a hell of a time figuring out what. Changing the
worker thread to be in an STA doesn't seem to change anything. Interestingly
(?) Marshal.IsComObject(this) returns false. The docs say that this is
supposed to return true for any class directly or indirectly derived from
COM.

Does anyone have any ideas, or can anyone tell me what I am doing wrong?

Thanks very much!

-- Ted