7

I have an application that is locking on the GUI thread, and I've used WinDbg, along with the "!clrstack" command to get this stack trace, but I can't figure out where the issue is. All of these methods look like framework methods, and none are mine. Any help would be much appreciated. I apologize for the long lines

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] 
Jon Tackabury
  • 47,710
  • 52
  • 130
  • 168
  • Are you attempting to modify a GUI object from a thread that does not own it? If so you could be running into the InvokeRequired problem. – Steven Behnke Feb 18 '09 at 00:26
  • As far as I know I'm not doing any cross-thread operations. I think I'm going to have an extensive code review to track this down. – Jon Tackabury Feb 18 '09 at 00:38
  • If anyone reading this thread is dealing with this problem being intermittent, one way to force a repro is to set an environment variable in a loop. Here's a sample .cmd file that sets a systemwide environment variable every ~5 seconds: code :top setx.exe foo bar ping.exe -n 5 localhost > nul goto top – JohnW Aug 09 '12 at 15:11

4 Answers4

8

It looks like this code isn't the true cause of the problem. See if one of these pages helps:

Update: Fixed url to first page.

David
  • 34,223
  • 3
  • 62
  • 80
  • I would expect .Net 3.x to behave the same way as .Net 2.0 in this case since the core DLLs are the same. – David Feb 18 '09 at 00:23
  • I'm pretty sure this is the issue... now it's just a matter of tracking down the offending control that is being created on the wrong thread somehow. – Jon Tackabury Feb 18 '09 at 02:47
  • Custom breakpoint (see my answer below) will get you there the fastest. – GregC Jun 16 '09 at 13:22
  • Hi David, these links are very helpful! However, the URL of the first blog changed: The port isn't appropriate anymore. If you could remove the port from the URL, such that both links work again? – chiccodoro Oct 22 '10 at 09:57
  • (i.e. the corrected link is: http://ikriv.com/en/prog/info/dotnet/MysteriousHang.html) – chiccodoro Oct 22 '10 at 11:27
3

The other answer comes from this Aaron Lerch. I really like the "filtered breakpoint on someone else's code" part. I think it would've saved me a couple of days.

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

GregC
  • 7,737
  • 2
  • 53
  • 67
1

I had similar issue, and found the culprit in our code.

Technique used: 0. Make sure in Spy++ that there are only two unmanaged threads with controls on them (WinForms and GDI+):

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

call this from UI thread upon init:

// 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. Remember managed id of Ui Thread in a singleton class.

  2. Search for all UserControls defined in our code. In each control's constructor, before calling InitializeComponent(), i placed code that checks current thread id against the main thread id. If they aren't equal, Assert(false).

  3. Subscribe to SystemEvents.UserPreferencesChanging. Debug.Assert(false) in handler: this happens before SystemEvents.UserPreferencesChanged, so debugger will hopefully pause here.

  4. Inspect list of subscribers to SystemEvents in the debugger. Find a subscriber in _handles dictionary of lists. Opening up SynchronizationContext of the each callback should reveal the problem: same thread id as for the control created on non-UI thread. SystemEvents will will execute event handler on that thread, deadlocking against UI thread.

GregC
  • 7,737
  • 2
  • 53
  • 67
0

The function CheckSystemEventsHandlersForFreeze() in this answer can help you to find root cause of why your GUI thread becomes locked.

Vlad Rudenko
  • 2,363
  • 1
  • 24
  • 24