tags:

views:

1038

answers:

4

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]
+7  A: 

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
Useful links, any developments for .net 3.x ?
Henk Holterman
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
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
Custom breakpoint (see my answer below) will get you there the fastest.
GregC
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
(i.e. the corrected link is: http://ikriv.com/en/prog/info/dotnet/MysteriousHang.html)
chiccodoro
+1  A: 

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
Excellent tips - thanks!
Jon Tackabury
+2  A: 

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
I've had (and continue to have) pretty good luck with it, at any rate. ;)
Aaron Lerch
A: 

Is there any way we can inspect subscribers to SystemEvents in C# code. I need to put the code in the application so that it generates a log if such things happen in my application in future

dheerajsharma14