0

我有一个 Web 应用程序,有时它挂起/执行非常慢。我使用 DebugDiag 进行了完整转储,并尝试使用 Crash/Hang 分析对其进行分析。

总结告诉我,我 7.86% 的线程 (10) 被阻塞并等待Monitor.Wait.

但是,当我使用线程检查调用堆栈/堆栈跟踪时,输出以下内容:

.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 

它实际上并没有告诉我他们正在等待获得哪个锁 - 关于如何获取这些信息的任何想法?

4

1 回答 1

1

不幸的是,看起来线程在调用 Monitor.Wait 之前并没有深入很多方法,因此可能更难确定确切的位置。根据堆栈跟踪,查看 Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() 的代码并查看它在哪里调用 Monitor.Wait 以查看它实际在等待什么。

根据代码的数量/质量,这可能是最简单的方法。您还可以安装 Windbg,找到它锁定的对象的地址并检查它,但需要进行一些初始配置以确保它可以加载所需的所有符号。http://blogs.msdn.com/b/emeadaxsupport/archive/2011/04/10/setting-up-windbg-and-using-symbols.aspx谈论 Windbg 设置。它是一个强大的工具,但仅检查 Quartz.Simpl.SimpleThreadPool+WorkerThread.Run() 的代码可能会更简单。

于 2012-11-28T23:08:23.197 回答