我有一个锁定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]
答案 0 :(得分:8)
看起来这段代码不是问题的真正原因。看看其中一个页面是否有帮助:
更新:修正了第一页的网址。
答案 1 :(得分:3)
另一个答案来自Aaron Lerch。我真的很喜欢“在其他人的代码上过滤断点”部分。我想这会让我节省几天。
答案 2 :(得分:1)
我有类似的问题,并在我们的代码中找到了罪魁祸首。
使用的技术: 0.确保在Spy ++中只有两个带有控件的非托管线程(WinForms和GDI +):
public static class ThreadingHelper_NativeMethods
{
[DllImport("user32.dll")]
public static extern bool IsGUIThread(bool bConvert);
}
在init上从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;
}));
}
在单例类中记住Ui Thread的托管ID。
搜索我们代码中定义的所有UserControl。在每个控件的构造函数中,在调用InitializeComponent()之前,我放置了检查当前线程id与主线程id的代码。如果它们不相等,则Assert(false)。
订阅SystemEvents.UserPreferencesChanging。处理程序中的Debug.Assert(false):这发生在SystemEvents.UserPreferencesChanged之前,因此调试器有望在这里暂停。
检查调试器中SystemEvents的订户列表。在_handles词典列表中查找订阅者。打开每个回调的SynchronizationContext应该揭示问题:与在非UI线程上创建的控件相同的线程ID。 SystemEvents将在该线程上执行事件处理程序,对UI线程进行死锁。
答案 3 :(得分:0)
this答案中的CheckSystemEventsHandlersForFreeze()函数可以帮助您找到导致GUI线程被锁定的根本原因。