1
votes

My code has deadlocked. Here is the stack trace for the main thread:

[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) + 0x14 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.GetMessage(ref System.Windows.Interop.MSG msg, System.IntPtr hwnd, int minMessage, int maxMessage) + 0x80 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0x75 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4b 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 MainDashboard.exe!MainDashboard.App.Main() + 0x59 bytes C# [Native to Managed Transition] [Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6b bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes [Native to Managed Transition]

How do I know what part of my code is responsible. The application entry point is:

MainDashboard.exe!MainDashboard.App.Main() + 0x59 bytes C#

and that is the only line in this stacktrace that is from my code.

Trying to view the call stack for two other frames displays the following:

The current thread is not currently running code all the call stack is could not be obtained.

Here is the call stack of another worker thread:

[Managed to Native Transition]

System.dll!Microsoft.Win32.SystemEvents.WindowThreadProc() + 0xaf bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes [Native to Managed Transition]

And here is the call stack of the last thread:

[Managed to Native Transition]

Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.WaitForThreadExit() + 0x93 bytes Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunParkingWindowThread() + 0x253 bytes mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes [Native to Managed Transition]

The app is hanged. there is a total of 49,000 records it needs to process. it stopped at 3,029. The app is not using any resources at this point. Task Manager is showing it using 0% CPU. The UI is responsive, but it is designed to be always responsive.

Also, this is not deterministic. I mean, if I restart the app, it will hang at a different point in the code, so there is not one record that has an issue that brings the whole thing down.

2
How does stack trace look for the other threads?Konrad Kokosa
Some versions of Visual Studio have a concurrency visualizer which should be able to do what you want.Chris Laplante
@kkokosa, I edited the question with the other call stacks.Barka
The fact that the processing has stopped does not mean that there's any deadlock. It may be something as simple as yours main-processing loop getting breaked improperly or some exception was thrown and some outer try/catch has jumped out of your main-processing loop and hence halted the process. If you had the debugger attached, check the Output for any first-chance exception notifications. Any NullReference, ArgumentOutOfRange, NotImplemented, InvalidOperation etc may be a sign of a bad errorhandling that simply halted your loop.quetzalcoatl
How about putting try ... catch in your threads and have them log the exceptions?Jim Mischel

2 Answers

4
votes

Since you now noticed 'first chance exceptions' in your 'Output' and they seem to kill your threads, there's one more thing other than just try/catch/log.

Use the debugging features of VS/CLR even further. Go to DEBUG menu, then EXCEPTIONS then find one (or all, but I prefer to do it one-by-one) of the exceptions you identified as thrown-and-killing-your-threads, i.e. InvalidOperationException and check the tick "thrown" or "unhandled" (depending on what you want and what version of VS you have).

Now, assuming you ticked "thrown", the IDE will automatically break/halt the program whenever it tried to throw exactly this one type of exception.

..and not only it will halt the program, it will also jump there as if you placed a breakpoint. You'll instantly get all the stacktraces, variables, code, etc you'd like to inspect.

But, on the other hand, if you app is spamming with this kind of exception with rate of thousands per second, just because someone was lazy and if/else'd some bad-arguments case and try/caught the exception instead, then trying to rely on this exception being "thrown" will .. well.. fail. In such case, you might want to try with "unhandled" tick instead (if you see it in the IDE at all), but of course it has its own limitations, too. Nevertheless, they are really precious tools if only you can attach the IDE to the failing process. Insta-break on the unknown line with problems!

-1
votes

Sounds like you're having troubles identifying what happened in your app and that you have no logging....

http://logging.apache.org/log4net/

When trying to solve these sorts of problems log files are invaluable.

Implement Log4net, configure it write to a log file and start logging stuff...

E.g. in places you suspect might be involved at the start of methods put

private void MethodName()
{
    logger.Debug("Begin MethodName");

and the end of methods

    logger.Debug("End MethodName");

Soon enough you'll get the clues you need.

You can customise what actually gets logged so that you can get verbose debug logging or just errors.

Also if you're not already using Visual Studio's "Debug Location" toolbar use it.