【问题标题】:Why do I see a call to WaitForMultipleObjectsEx in this method?为什么我会在此方法中看到对 WaitForMultipleObjectsEx 的调用?
【发布时间】:2011-11-25 17:08:54
【问题描述】:

我有一个 .NET Windows 窗体应用程序,它偶尔会进入挂起状态。当我转储进程并通过 WinDbg/SOS 打开它时,它显示一个线程调用了kernel32!WaitForMultipleObjectsEx,尽管我没有在该特定方法中的任何事件对象上调用任何 WaitXXX API。这在我正在检查 InvokedRequired 和 IsDisposed API 中说过。对 InvokedRequired 或 IsDisposed API 的任何调用是否会在内部调用任何 WaitXXX API?

这里是线程的调用栈。

[HelperMethodFrame_1OBJ: 0e4eedc0] System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)  
0e4eee6c 67b7689f System.Threading.WaitHandle.WaitOne(Int64, Boolean)  
0e4eee88 67b76855 System.Threading.WaitHandle.WaitOne(Int32, Boolean)  
0e4eee9c 65c21a4f System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle)  
0e4eeeb0 65f5d68b System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean)  
0e4eef50 65c233ac System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[])  
0e4eef84 65c2334f System.Windows.Forms.Control.Invoke(System.Delegate)  
0e4eef88 6715ad76 MyNameSpace.MyClass.MyMethod()  
0e4eefb0 67b96e96 System.Threading.ThreadHelper.ThreadStart_Context(System.Object)  
0e4eefbc 67ba031f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)  
0e4eefd4 67b96e14 System.Threading.ThreadHelper.ThreadStart()  
0e4ef1fc 68f81b4c [GCFrame: 0e4ef1fc]   

【问题讨论】:

  • 您为什么不向我们展示您的代码当时在做什么?

标签: c# multithreading windbg sos


【解决方案1】:

Check out this postthis post 他们会很有帮助,他们会向您展示不同 .NET 线程的所有正常调用,所以只需比较并找出问题所在..

编辑:
This great post 详细说明了调用时调用 WaitOne API 的原因以及发生挂起的原因。了解细节可能会帮助您避免这些挂起。

【讨论】:

  • 感谢 HaLaBi,我在这里谈论的线程正在调用我的一种方法,所以我认为这个方法不能被忽略。不过我已经读过那个博客了。
  • 这篇关于 WaitOne API 的帖子真的很有帮助
【解决方案2】:

Win32(以及 .NET)中的许多操作都会阻塞。因为在所有阻塞 API 之下实际上是一个带有等待的异步调用,所以当用户线程正在等待来自内核线程的某些东西时,这种等待调用是堆栈上的一个常见特性。

更新(现在我看到了你的调用堆栈):等待是因为调用Invoke 的线程需要等待UI 线程完成操作才能返回。 WaitForMultipleObjectsEx 是任何用户模式等待内核句柄(在这种情况下可能是一个事件对象)的底层等待 API。

【讨论】:

    【解决方案3】:

    有很多 .Net 方法在内部执行等待。

    例如,Control.Invoke 将等待事件句柄,直到 UI 线程运行回调。

    【讨论】:

    • 应用程序在调用 Invoke 时挂起是什么意思?还有关于如何最好地调用 Control.Invoke 的任何链接/建议/设计模式?
    • 如果你有一个死锁就会发生这种情况 - 如果 UI 线程正在等待该线程完成。使用调试器查看调用堆栈并找出您的代码在做什么。
    • 感谢您的提示。我已经查看了所有托管线程的 !threads 命令和 LockCount =0。 !syncBlk 输出也一无所有。似乎不是僵局。因为这是我看到调用我的代码并且处于等待状态的唯一托管线程
    猜你喜欢
    • 2020-10-05
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    相关资源
    最近更新 更多