C# Monitor.Wait and VB6 message pumping and events

ccommultithreadingnetvb6

I have a com callable wrapper written in C#. The wrapper uses a Socket internally to SendAsync and ReceiveAsync. In order to make this appear synchronous to the VB6 code that calls this wrapper, I use Monitor.Wait.

I can't figure out if Monitor.Wait pumps messages while it blocks. According to cbrumme's blog over on MSDN

I mentioned above that managed
blocking will perform some pumping
when called on an STA thread.
Managed blocking includes a
contentious Monitor.Enter,
WaitHandle.WaitOne,
WaitHandle.WaitAny,
GC.WaitForPendingFinalizers, our
ReaderWriterLock and Thread.Join. It
also includes anything else in FX that
calls down to these routines.

I don't see Monitor.Wait on that list, but he also says "also includes anything else in FX that calls down to these routines". I used Reflector to see if Monitor.Wait calls any of those routines and from what I can see, it doesn't. Here is another article that I read as well.

I couldn't find anything more definitive on this subject, so would just like to confirm that this extremely simplified example is wrong:

public bool SendAndReceiveCalledFromVb6()
{
    SendRecvToken token = SendAsync();
    /// wait for receive using Monitor.Wait.
    if(!token.EndedSynchronously) Monitor.Wait(token.anObjThatGetsPulsed);
    return token.Result;
}

and that I'd be better off with something like this:

public bool SendAndReceiveCalledFromVb6()
{
    SendRecvToken token = SendAsync();
    /// wait for receive using ManualResetEvent.WaitOne.
    token.aManualResetEvt.WaitOne();
    return token.Result;
}

Also, I notice that when I raise a COM event from my C# code, the VB6 event handler gets executed in the proper thread. It would be useful to know if .Net is using SendMessage or PostMessage to marshall the event.

Thank you.

Best Answer

It's been awhile since I had to dig down to that level, but the best way to figure this out is probably to turn on unmanaged debugging and symbol download in Visual Studio, disable "just my code", set a breakpoint at the Monitor.Wait call, then attach to the process and step in (let it take you to assembly view). Then you can just step around and watch the call stack window- it'll tell you if SendMessage is called, and if any pumping is going on. A lot of these kinds of internals questions are best answered emprirically. :)