Why does .NET raise_XXX proxy code lock on a mutex.

  • Thread starter Thread starter daniel
  • Start date Start date
D

daniel

Maybe I'm not understanding things.

I have a multi-threaded callback producer (Unmanaged C++), which fires
into a managed proxy class, which in turn calls into a managed C++
consumer (mixed mode DLL). From the managed C++ class I have defined
__events, which are consumed by a C# class. This works perfectly well;
All the callbacks end up in the managed c++ class and successfully
call into the C# code, however the raise_XXX method for the event
appears to lock on a mutex, so if the C# consumer takes too long,
events are queued/blocked in the managed C++ code. This seems like
quite a poor implementation. I know how to work around it, however I'd
prefer to use the delegate-event model, but obviously can't live with
it blocking!

So I have 2 questions.

1. Why was it implemented this way.
2. Is there any way to have it not do this (some sort of compiler
directive??)

Thanks.

D.
 
I have a multi-threaded callback producer (Unmanaged C++), which fires
into a managed proxy class, which in turn calls into a managed C++
consumer (mixed mode DLL). From the managed C++ class I have defined
__events, which are consumed by a C# class. This works perfectly well;
All the callbacks end up in the managed c++ class and successfully
call into the C# code, however the raise_XXX method for the event
appears to lock on a mutex, so if the C# consumer takes too long,
events are queued/blocked in the managed C++ code. This seems like
quite a poor implementation. I know how to work around it, however I'd
prefer to use the delegate-event model, but obviously can't live with
it blocking!

So I have 2 questions.

1. Why was it implemented this way.
2. Is there any way to have it not do this (some sort of compiler
directive??)

raise_XXX checks handler on null and then if it's possible calls handler
itself. To avoid concurency problems it puts these two operations in a lock.
You can call the handler as:

XXXHandler handler = this->xxxHandler;

if (handler != 0)
handler->Invoke(...);

Result is the same.
 
raise_XXXchecks handler on null and then if it's possible calls handler
itself. To avoid concurency problems it puts these two operations in alock.

"To avoid concurrency problems" is a pretty poor reason for a mutex
lock....I would have thought that currency issues in a multi-threaded
application would be the responsibility of the programmer! Unless,
there is a way to switch the locking semantics, I'd file this one
under one of the poorest default framework implementations from
Microsoft, EVER!
You can call the handler as:

XXXHandler handler = this->xxxHandler;

if (handler != 0)
handler->Invoke(...);

Result is the same.

....so you're saying that there is no way to override the global
locking for delegates?

D.
 
raise_XXXchecks handler on null and then if it's possible calls handler
"To avoid concurrency problems" is a pretty poor reason for a mutex
lock....I would have thought that currency issues in a multi-threaded
application would be the responsibility of the programmer! Unless,
there is a way to switch the locking semantics, I'd file this one
under one of the poorest default framework implementations from
Microsoft, EVER!

MC++ generates such a lock in order to prevent null reference exception in
raise_XXX method:

if (this->handler != 0)
this->handler->Invoke(...);

I did not see that C# generated raise_XXX method at all. Thus MC++ provides
more but in safe box.
...so you're saying that there is no way to override the global
locking for delegates?

Do not know exactly. It's not so hard however to call handler->Invoke(...)
directly.
 
Back
Top