6

我有一个锁定在 GUI 线程上的应用程序,并且我使用了 WinDbg 以及“!clrstack”命令来获取此堆栈跟踪,但我不知道问题出在哪里。所有这些方法看起来都像框架方法,没有一个是我的。任何帮助将非常感激。我为排长队道歉

OS Thread Id: 0x724 (0)
ESP       EIP     
0012ec88 7c90e4f4 [HelperMethodFrame_1OBJ: 0012ec88] System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)
0012ed34 792b687f System.Threading.WaitHandle.WaitOne(Int64, Boolean)
0012ed50 792b6835 System.Threading.WaitHandle.WaitOne(Int32, Boolean)
0012ed64 7b6f192f System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle)
0012ed78 7ba2d0bb System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean)
0012ee18 7b6f328c System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[])
0012ee4c 7b920717 System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback, System.Object)
0012ee64 7a924102 Microsoft.Win32.SystemEvents+SystemEventInvokeInfo.Invoke(Boolean, System.Object[])
0012ee98 7a922833 Microsoft.Win32.SystemEvents.RaiseEvent(Boolean, System.Object, System.Object[])
0012eee4 7a923d2f Microsoft.Win32.SystemEvents.OnUserPreferenceChanged(Int32, IntPtr, IntPtr)
0012ef04 7aa8f184 Microsoft.Win32.SystemEvents.WindowProc(IntPtr, Int32, IntPtr, IntPtr)
0012ef08 003620a4 [InlinedCallFrame: 0012ef08] 
0012f0cc 7b1d8cce System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
0012f168 7b1d8937 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
0012f1bc 7b1d8781 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
0012f1ec 7b195911 System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
0012f200 00eb0ebb WinForms1.Program.Main()
0012f69c 79e71b4c [GCFrame: 0012f69c] 
4

4 回答 4

8

看起来这段代码不是问题的真正原因。看看这些页面之一是否有帮助:

更新:固定网址到第一页。

于 2009-02-17T23:53:33.690 回答
3

另一个答案来自这个 Aaron Lerch。我真的很喜欢“在别人的代码上过滤断点”部分。我想它会为我节省几天的时间。

http://www.aaronlerch.com/blog/2008/12/15/debugging-ui/

于 2009-05-01T15:02:00.617 回答
1

我有类似的问题,并在我们的代码中找到了罪魁祸首。

使用的技术: 0. 确保在 Spy++ 中只有两个非托管线程带有控件(WinForms 和 GDI+):

public static class ThreadingHelper_NativeMethods
{
   [DllImport("user32.dll")]
   public static extern bool IsGUIThread(bool bConvert);
}

在初始化时从 UI 线程调用它:

// This code forces initialization of .NET BroadcastEventWindow to the UI thread.
// http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/fb267827-1765-4bd9-ae2f-0abbd5a2ae22
if (ThreadingHelper_NativeMethods.IsGUIThread(false))
{
    Microsoft.Win32.SystemEvents.InvokeOnEventsThread(new MethodInvoker(delegate()
    {
    int x = 0;
    }));
}
  1. 记住单例类中 Ui 线程的托管 id。

  2. 搜索我们代码中定义的所有用户控件。在每个控件的构造函数中,在调用 InitializeComponent() 之前,我放置了检查当前线程 id 与主线程 id 的代码。如果它们不相等,则断言(假)。

  3. 订阅 SystemEvents.UserPreferencesChanging。处理程序中的 Debug.Assert(false):这发生在 SystemEvents.UserPreferencesChanged 之前,因此调试器有望在此处暂停。

  4. 在调试器中检查 SystemEvents 的订阅者列表。在 _handles 列表字典中查找订阅者。打开每个回调的 SynchronizationContext 应该会发现问题:与在非 UI 线程上创建的控件相同的线程 id。SystemEvents 将在该线程上执行事件处理程序,对 UI 线程进行死锁。

于 2009-04-28T16:27:47.940 回答
0

答案中的函数 CheckSystemEventsHandlersForFreeze()可以帮助您找到 GUI 线程被锁定的根本原因。

于 2018-10-11T08:58:31.600 回答