Reputation: 6483
I have a web application and sometimes it is hanging / performing very slow. I have taken a full dump using DebugDiag, and tried to analyse it using the Crash/Hang analysis.
The summary gave me that 7.86% of my threads (10) are blocked and waiting for Monitor.Wait
.
However, when I check the Call Stack / Stack Trace with the thread, the below is outputted:
.NET Call Stack
Function
System.Threading.Monitor.ObjWait(Boolean, Int32, System.Object)
System.Threading.Monitor.Wait(System.Object, Int32, Boolean)
Quartz.Simpl.SimpleThreadPool+WorkerThread.Run()
System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
System.Threading.ExecutionContext.runTryCode(System.Object)
System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode, CleanupCode, System.Object)
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
System.Threading.ThreadHelper.ThreadStart()
Full Call Stack
Function Source
ntdll!NtWaitForMultipleObjects+15
KERNELBASE!WaitForMultipleObjectsEx+100
kernel32!WaitForMultipleObjectsExImplementation+e0
clr!WaitForMultipleObjectsEx_SO_TOLERANT+56
clr!Thread::DoAppropriateAptStateWait+4d
clr!Thread::DoAppropriateWaitWorker+17d
clr!Thread::DoAppropriateWait+60
clr!CLREvent::WaitEx+106
clr!CLREvent::Wait+19
clr!Thread::Wait+1d
clr!Thread::Block+1a
clr!SyncBlock::Wait+169
clr!ObjHeader::Wait+2c
clr!ObjectNative::WaitTimeout+147
System.Threading.Monitor.Wait(System.Object, Int32, Boolean)
System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
System.Threading.ExecutionContext.runTryCode(System.Object)
clr!CallDescrWorker+33
clr!CallDescrWorkerWithHandler+8e
clr!MethodDesc::CallDescr+194
clr!MethodDesc::CallTargetWorker+21
clr!MethodDescCallSite::Call+1c
clr!ExecuteCodeWithGuaranteedCleanupHelper+bb
clr!ReflectionInvocation::ExecuteCodeWithGuaranteedCleanup+138
System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
System.Threading.ThreadHelper.ThreadStart()
clr!CallDescrWorker+33
clr!CallDescrWorkerWithHandler+8e
clr!MethodDesc::CallDescr+194
clr!MethodDesc::CallTargetWorker+21
clr!ThreadNative::KickOffThread_Worker+1e1
clr!Thread::DoExtraWorkForFinalizer+114
clr!Thread::ShouldChangeAbortToUnload+101
clr!Thread::ShouldChangeAbortToUnload+399
clr!Thread::RaiseCrossContextException+3f8
clr!Thread::DoADCallBack+358
clr!Thread::DoExtraWorkForFinalizer+fa
clr!Thread::ShouldChangeAbortToUnload+101
clr!Thread::ShouldChangeAbortToUnload+399
clr!Thread::ShouldChangeAbortToUnload+43a
clr!ManagedThreadBase::KickOff+15
clr!ThreadNative::KickOffThread+23e
clr!Thread::intermediateThreadProc+4b
kernel32!BaseThreadInitThunk+e
ntdll!__RtlUserThreadStart+70
ntdll!_RtlUserThreadStart+1b
It doesn't actually show me which lock they are waiting to obtain - Any idea on how to get this information?
Upvotes: 0
Views: 3796
Reputation: 131
Unfortunately it looks like the thread doesn't go very many methods deep before calling Monitor.Wait, so it may be harder to pinpoint the exact location. Based off the stack trace, look at the code for Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() and see where it calls Monitor.Wait to see what it is actually waiting on.
Depending on the volume/quality of code, that is probably the easy way. You could also install Windbg, locate the address of the object it is locking on, and examine it, but there's some initial configuration required to make sure it can load up all the symbols it needs. http://blogs.msdn.com/b/emeadaxsupport/archive/2011/04/10/setting-up-windbg-and-using-symbols.aspx talks about Windbg setup. It is a powerful tool, but just checking the code for Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() will probably be simpler.
Upvotes: 1