Not long after upgrading to VS2010, my application won't shut down cleanly. If I close the app and then hit pause in the IDE, I see this:
The problem is, there's no context. The call stack just says [External code], which isn't too helpful.
Here's what I've done so far to try to narrow down the problem:
While I could do the next brute force step, which is to roll my code back to a point where this didn't happen and then look over all of the change logs, this isn't terribly efficient. Can anyone recommend a better way to figure this out, given the notable lack of information presented by the debugger?
The only other things I can think of include:
UPDATE
Perhaps this information will be of use. I decided to use WinDbg and attach to my application. I then closed it, and switched to thread 0 and dumped the stack contents. Here's what I have:
ThreadCount: 6
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 4
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
0 1 1c70 005a65c8 6020 Enabled 02dac6e0:02dad7f8 005a03c0 0 STA
2 2 1b20 005b1980 b220 Enabled 00000000:00000000 005a03c0 0 MTA (Finalizer)
XXXX 3 08504048 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
XXXX 4 08504540 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
XXXX 5 08516a90 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
XXXX 6 08517260 19820 Enabled 00000000:00000000 005a03c0 0 Ukn
0:008> ~0s
eax=c0674960 ebx=00000000 ecx=00000000 edx=00000000 esi=0040f320 edi=005a65c8
eip=76c37e47 esp=0040f23c ebp=0040f258 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
USER32!NtUserGetMessage+0x15:
76c37e47 83c404 add esp,4
0:000> !clrstack
OS Thread Id: 0x1c70 (0)
Child SP IP Call Site
0040f274 76c37e47 [InlinedCallFrame: 0040f274]
0040f270 6baa8976 DomainBoundILStubClass.IL_STUB_PInvoke(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\WindowsBase\d17606e813f01376bd0def23726ecc62\WindowsBase.ni.dll
0040f274 6ba924c5 [InlinedCallFrame: 0040f274] MS.Win32.UnsafeNativeMethods.IntGetMessageW(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)
0040f2c4 6ba924c5 MS.Win32.UnsafeNativeMethods.GetMessageW(System.Windows.Interop.MSG ByRef, System.Runtime.InteropServices.HandleRef, Int32, Int32)
0040f2dc 6ba8e5f8 System.Windows.Threading.Dispatcher.GetMessage(System.Windows.Interop.MSG ByRef, IntPtr, Int32, Int32)
0040f318 6ba8d579 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
0040f368 6ba8d2a1 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
0040f374 6ba7fba0 System.Windows.Threading.Dispatcher.Run()
0040f380 62e6ccbb System.Windows.Application.RunDispatcher(System.Object)*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\PresentationFramewo#\7f91eecda3ff7ce478146b6458580c98\PresentationFramework.ni.dll
0040f38c 62e6c8ff System.Windows.Application.RunInternal(System.Windows.Window)
0040f3b0 62e6c682 System.Windows.Application.Run(System.Windows.Window)
0040f3c0 62e6c30b System.Windows.Application.Run()
0040f3cc 001f00bc MyApplication.App.Main() [C:\code\trunk\MyApplication\obj\Debug\GeneratedInternalTypeHelper.g.cs @ 24]
0040f608 66c421db [GCFrame: 0040f608]
EDIT -- not sure if this helps, but the main thread's call stack looks like this:
[Managed to Native Transition]
> WindowsBase.dll!MS.Win32.UnsafeNativeMethods.GetMessageW(ref System.Windows.Interop.MSG msg, System.Runtime.InteropServices.HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) + 0x15 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x48 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame = {System.Windows.Threading.DispatcherFrame}) + 0x85 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x17 bytes
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes
PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes
I did a search on it and found some posts related to WPF GUIs hanging, and maybe that'll give me some more clues.
To display the Threads window in break mode or run mode While Visual Studio is in debug mode, select the Debug menu, point to Windows, and then select Threads.
Worker thread is a continuous parallel thread that runs and accepts messages until the time it is explicitly closed or terminated. Messages to a worker thread can be sent from the parent thread or its child worker threads. Through out this document, parent thread is referred as thread where a worker thread is spawned.
Android has four basic types of threads. You'll see other documentation talk about even more, but we're going to focus on Thread , Handler , AsyncTask , and something called HandlerThread .
Add the following handler to every window your application creates in a separate thread:
win.Closed += (o, e) => win.Dispatcher.InvokeShutdown();
If the main thread hangs, call win.Dispatcher.InvokeShutdown()
in MainWindow.Closed
- this will automatically close all other windows created in the Main thread.
Without this handler, my application with the following code hanged on exit too:
void Worker() {
var win = new Window();
// win.Closed += onWindowClose ?? ((o, e) => editor.Dispatcher.InvokeShutdown());
editor.Show();
System.Windows.Threading.Dispatcher.Run();
}
The worker thread Id you are seeing is 0. This is a framework thread and is expected - it is not a thread that the program has "spawned". If you attach to any .Net process you will see this. I'm not sure which framework thread it is - definitely not the finalizer thread as this is never thread 0. Perhaps a JIT thread?
What is more interesting then is your main thread, as this appears to be hanging. I would concentrate on debugging your main thread to bottom this out. Has it deadlocked itself from a window closed event handler waiting for something that will never happen for example?
Update
After reading the stack trace for the main thread added to the question, it would be interesting to run a test to bottom out whether the main thread is stalled or whether it is simply idle waiting for a message (and that it is waiting for a WM_CLOSE that it never received or was never sent).
The code below can be used to manually send a WM_CLOSE message to your application. Simply wait for your program to hang when you have shut it down, and then run the code. Replace the process name with your own.
Update 2
Ok, it looks like the main thread is well and truly hung as it is not processing WM_CLOSE or WM_QUIT messages.
Please try and make the smallest application that can reproduce the issue and post the code.
Example WM_CLOSE\WM_QUIT App
internal class Program
{
private const int WM_QUIT = 0x0012;
private const int WM_CLOSE = 0x0010;
[DllImport("user32.dll")]
private static extern bool PostMessage(int hhwnd, uint msg, IntPtr wParam, IntPtr lParam);
private static void Main()
{
Process p = GetProcess("Your process name - no '.exe' required");
CloseMainWindow(p);
}
private static Process GetProcess(string name)
{
List<Process> processes = Process.GetProcessesByName(name).ToList();
if (processes.Count != 1)
{
throw new Exception(
"Expected 1 process with name '" + name +
"' but found " + processes.Count + ".");
}
return processes[0];
}
private static void CloseMainWindow(Process p)
{
PostMessage(p, WM_CLOSE, "close");
}
private static void QuitApplication(Process p)
{
PostMessage(p, WM_QUIT, "quit");
}
private static void PostMessage(Process p, uint message, string name)
{
Console.WriteLine("Posting {0} message to '{1}'...", name, p.ProcessName);
bool succeeded = PostMessage(p.MainWindowHandle.ToInt32(), message, IntPtr.Zero, IntPtr.Zero);
Console.WriteLine("Posted {0} message to '{1}' (succeeded:{2}).", name, p.ProcessName, succeeded);
}
}
I finally figured out this problem. I had a control that was Import
ed by MEF, but not actually ever called (yet). I think MEF instantiated it even though it wasn't referenced anywhere (I was under the assumption that creation didn't occur until the resource was requested, but apparently I was wrong). I fixed the issue by using Lazy<> instantiation, and now it works. This one really threw me, but thanks everyone for the help. I learned a lot trying to debug this problem.
If you are creating the worker threads (rather than pool threads), set their Name to something descriptive on creation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With