C#Monitor.Wait和VB6消息泵送和事件

时间:2009-10-16 05:26:11

标签: c# .net multithreading com vb6

我有一个用C#编写的com可调用包装器。包装器在内部使用Socket来发送SendAsync和ReceiveAsync。为了使它看起来与调用此包装器的VB6代码同步,我使用Monitor.Wait。

我无法弄清楚Monitor.Wait是否在阻止消息时泵送消息。根据{{​​3}} -

  

我上面提到过托管   阻塞将执行一些抽水   在STA线程上调用时。
  托管阻止包括a   有争议的Monitor.Enter,   WaitHandle.WaitOne,   WaitHandle.WaitAny,   GC.WaitForPendingFinalizers,我们的   ReaderWriterLock和Thread.Join。它   还包括FX中的任何其他内容   调用这些例程。

我没有在列表中看到Monitor.Wait,但他也说“还包括FX中的其他任何调用这些例程的东西”。我使用Reflector来查看Monitor.Wait是否调用了这些例程,而且从我看到的情况来看,它没有。 cbrumme's blog over on MSDN是我读过的另一篇文章。

我在这个主题上找不到更明确的内容,所以我想确认这个非常简化的示例是错误的:

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

并且我会用这样的东西变得更好:

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

另外,我注意到当我从C#代码中引发COM事件时,VB6事件处理程序在适当的线程中执行。知道.Net是否使用SendMessage或PostMessage来策划事件将是有用的。

谢谢。

2 个答案:

答案 0 :(得分:0)

已经有一段时间了,因为我不得不深入到这个级别,但最好的解决方法可能是在Visual Studio中打开非托管调试和符号下载,禁用“只是我的代码”,在Monitor.Wait调用,然后附加到进程并单步执行(让它进入程序集视图)。然后你可以逛逛并观察调用堆栈窗口 - 它会告诉你是否调用了SendMessage,以及是否正在进行任何抽取。许多这类内部问题最好在经验上得到解答。 :)

答案 1 :(得分:0)

经过一些测试后,我得出的结论是,Monitor.Wait确实提取了消息以及EventWaitHandle Wait方法。