我有一个用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来策划事件将是有用的。
谢谢。
答案 0 :(得分:0)
已经有一段时间了,因为我不得不深入到这个级别,但最好的解决方法可能是在Visual Studio中打开非托管调试和符号下载,禁用“只是我的代码”,在Monitor.Wait调用,然后附加到进程并单步执行(让它进入程序集视图)。然后你可以逛逛并观察调用堆栈窗口 - 它会告诉你是否调用了SendMessage,以及是否正在进行任何抽取。许多这类内部问题最好在经验上得到解答。 :)
答案 1 :(得分:0)
经过一些测试后,我得出的结论是,Monitor.Wait确实提取了消息以及EventWaitHandle Wait方法。