P/Invoke, [STAThread()] and multi threading

I

igd

I am forced to decorate my .NET Main()-method with [STAThread()], since
an unmanaged function (which i am calling through P/Invoke) calls
CoCreateInstance() in turn. The problem is, that another unmanaged
function starts a new thread which invokes a callback function. This
callback function is a delegate in my .NET app and since it is executed
in a STA (Singe Threaded Appartment), the callback function/delegate
can not called right. Is there a possibility to fix this dilemma?

Thanks in advance!

- igd -
 
W

Willy Denoyette [MVP]

igd said:
I am forced to decorate my .NET Main()-method with [STAThread()], since
an unmanaged function (which i am calling through P/Invoke) calls
CoCreateInstance() in turn. The problem is, that another unmanaged
function starts a new thread which invokes a callback function. This
callback function is a delegate in my .NET app and since it is executed
in a STA (Singe Threaded Appartment), the callback function/delegate
can not called right. Is there a possibility to fix this dilemma?

Thanks in advance!

- igd -


STA threads and native callbacks are not related unless you are talking about COM callbacks,
what exactly is not working as you expect?

Willy.
 
I

igd

The unmanaged server wrappes a COM server, i.e. when I call the
unmanaged function ASIOStart() through P/Invoke it calls IASIO::start()
in turn, which is a method of a COM interface. The IASIO::start()
method creates a new thread. This new thread calls the callback
function (a delegate in my .NET client).

The callback function prototypes:

void bufferSwitch(long index, ASIOBool processNow);
ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool
processNow);

The COM server after all invokes unmanaged callbacks (?).

Summary:

(1) Encapsulated COM client starts new thread with CreateThread()
(2) new thread calls unmanaged callback function
(3) callback function is actually a delegate in STA .NET client

When the new thread try to call the callback function the following
message appears:

"An unhandled win32 exception occured in Test.vshost.exe [2252]"
 
W

Willy Denoyette [MVP]

igd said:
The unmanaged server wrappes a COM server, i.e. when I call the
unmanaged function ASIOStart() through P/Invoke it calls IASIO::start()
in turn, which is a method of a COM interface. The IASIO::start()
method creates a new thread. This new thread calls the callback
function (a delegate in my .NET client).

The callback function prototypes:

void bufferSwitch(long index, ASIOBool processNow);

long in C# is 64 bit! This should be an int.

ASIOTime *bufferSwitchTimeInfo(ASIOTime *timeInfo, long index, ASIOBool
processNow);

The COM server after all invokes unmanaged callbacks (?).

COM callbacks are called on interfaces (ConnectionPoint) passed to them by the client, IMO
this is not what you are doing here.
Note that as I said in another thread of yours, that the Encapsulated C native dll is the
COM client here, I'm having the impression that you are incorrectly mixing both interop
models, IMO you should call the COM object from C# directly, that is, your C# code should be
the client.

Summary:

(1) Encapsulated COM client starts new thread with CreateThread()
As said in another thread, it's up to the client to initialize the threads apartment, which
he fails to do, that's why you had to set the STAThread attribute on Main.
Question is what's the thread is used for?
Is the COM instance (CoCreateInstance) created on this thread?
How is this thread initialized? STA or other or none?
What kind of COM object is this, STA or other, regular COM server or ActiveX server?
(2) new thread calls unmanaged callback function
What kind of callback, native or COM?
(3) callback function is actually a delegate in STA .NET client
Good if the callback is a simple native callback, wrong if it's a COM callback.
Willy.
 
I

igd

void bufferSwitch(long index, long processNow);
long in C# is 64 bit! This should be an int.

Yes i know. This was the prototype declared in the native client. I map
this callback function to the following .net delegate:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void BufferSwitchCallback(int doubleBufferIndex, int
directProcess);

But that is not the point. Concrete:

There is a unmanaged function which expect a pointer to a structure
containig four callback function pointers (class with four delegates in
..net). Two of that callback function are called from the same thread
and >IT WORKS<. The other two callbacks are called from the new thread
the COM server created and do NOT work. the callback prototypes are
defined in the NATIVE client, NOT in the COM server. the native client
give that struct pointer direct to the COM server:

ASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long
numChannels,
long bufferSize, ASIOCallbacks *callbacks) // native function
{
// ...
return theAsioDriver->createBuffers(bufferInfos, numChannels,
bufferSize, callbacks); // COM interface
}

The COM server then use this structure this way:

this->callbacks = callbacks;
callbacks->bufferSwitchCallback (...); // just use NATIVE callbacks



Unfortunately I MUST NOT use the COM server direct and MUST go through
the unmanaged wrapper.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top