.net 到达MemberInfoCache.AddMethod()时,新的StackTrace(线程,bool)挂起

.net 到达MemberInfoCache.AddMethod()时,新的StackTrace(线程,bool)挂起,.net,multithreading,freeze,system.diagnostics,.net,Multithreading,Freeze,System.diagnostics,我正在编写代码,在我们的多用户多线程应用服务器中实现某种进程内探查器组件。它基本上工作得很完美-显示每个线程的堆栈跟踪,以及一些附加信息,如该线程的CPU利用率、SQL等待时间等,每X秒刷新一次。我差点签入,但突然在调试会话中注意到我的应用程序挂起了!它并非总是发生,而是随机发生的,暗示着一些并发性问题。经过仔细检查,我看到应用程序在调用新的StackTraceone_of_my_线程时被挂起,false。以下是调试器的堆栈: [Managed to Native Transition] m

我正在编写代码,在我们的多用户多线程应用服务器中实现某种进程内探查器组件。它基本上工作得很完美-显示每个线程的堆栈跟踪,以及一些附加信息,如该线程的CPU利用率、SQL等待时间等,每X秒刷新一次。我差点签入,但突然在调试会话中注意到我的应用程序挂起了!它并非总是发生,而是随机发生的,暗示着一些并发性问题。经过仔细检查,我看到应用程序在调用新的StackTraceone_of_my_线程时被挂起,false。以下是调试器的堆栈:

[Managed to Native Transition]  
mscorlib.dll!System.RuntimeType.RuntimeTypeCache.MemberInfoCache<System.Reflection.RuntimeMethodInfo>.AddMethod(System.RuntimeTypeHandle declaringType = {System.RuntimeTypeHandle}, System.RuntimeMethodHandle method, System.RuntimeType.RuntimeTypeCache.CacheType cacheType) + 0x88 bytes   
mscorlib.dll!System.RuntimeType.RuntimeTypeCache.GetMethod(System.RuntimeTypeHandle declaringType, System.RuntimeMethodHandle method) + 0x2d bytes  
mscorlib.dll!System.RuntimeType.GetMethodBase(System.RuntimeTypeHandle reflectedTypeHandle, System.RuntimeMethodHandle methodHandle) + 0xf5 bytes   
mscorlib.dll!System.Diagnostics.StackFrameHelper.GetMethodBase(int i) + 0x4e bytes  
mscorlib.dll!System.Diagnostics.StackTrace.CaptureStackTrace(int iSkip, bool fNeedFileInfo = false, System.Threading.Thread targetThread, System.Exception e = null) + 0xb8 bytes   

mscorlib.dll!System.Diagnostics.StackTrace.StackTrace(System.Threading.Thread targetThread, bool needFileInfo) + 0x18 bytes 

>Almog.Next.Tools.dll!Almog.Next.Services.ThreadWorkUnit.GetStackTrace(System.Threading.Thread th = {System.Threading.Thread}, Almog.Next.Services.StackDetalization details = Simplified) Line 175 + 0x2c bytes    

Almog.Next.Tools.dll!Almog.Next.Services.ThreadWorkUnit.InternalCalculate(Almog.Next.Services.StackDetalization sdetails = Simplified) Line 131 + 0x1b bytes

Almog.Next.Tools.dll!Almog.Next.Services.ThreadWorkUnit.Calculate(Almog.Next.Services.StackDetalization sdetails = Simplified) Line 90 + 0xc bytes

Almog.Next.Tools.dll!Almog.Next.Services.InProcessProfiler.GetThreadWorks(Almog.Next.Services.StackDetalization stackLevel = Simplified) Line 41 + 0xe bytes

Almog.Next.Tools.dll!Almog.Next.CommonControls.ShowWorkloadForm.timer_Tick(object sender = {Interval = 250}, System.EventArgs e = {System.EventArgs}) Line 40 + 0x9 bytes

System.Windows.Forms.dll!System.Windows.Forms.Timer.OnTick(System.EventArgs e) + 0x17 bytes 

System.Windows.Forms.dll!System.Windows.Forms.Timer.TimerNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x34 bytes  

System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(System.IntPtr hWnd, int msg = 275, System.IntPtr wparam, System.IntPtr lparam) + 0x5a bytes 

[Native to Managed Transition]  

[Managed to Native Transition]  

System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int dwComponentID, int reason = -1, int pvLoopData = 0) + 0x24e bytes 

System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0x177 bytes 

System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x61 bytes    

System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.Form mainForm) + 0x31 bytes  

NextServer.exe!Almog.Next.Server.Program.Main(string[] ParamStr = {string[0]}) Line 24 + 0x1d bytes
我相信每一个新的方法都与MemberInfoCache有关,但即使在使用Reflector查看AddMethod的代码之后,我也不知道我能做些什么。 求求你,救命!我完全卡住了

下面是代码读取堆栈跟踪。没什么不寻常的,伊莫:


提前感谢…

如果您挂起的线程持有锁,并且StackTrace正在使用该锁,那么您将死锁

不推荐使用Thread.Suspend的原因是:您基本上无法安全地使用它。只有当您确切地知道挂起线程正在运行的代码(包括任何BCL内容)时,才能使用它。你不可能知道


我不知道解决这个问题的办法。我想线程需要挂起才能捕获stacktrace?

从这里开始:如果使用不是当前线程的目标线程创建stacktrace,则必须首先挂起目标线程。确定。我看不到一个安全的方法来使用这个API。除非您可以在不同的appdomain中运行堆栈跟踪代码?能否跨应用程序域封送线程对象?然后,它将是安全的,因为没有共享状态,甚至没有反射缓存。我不知道如何封送线程。它既不可序列化,也不继承MarshalByRef。卡住了。卡住了。卡住了…至少可以序列化当前线程。通过进行跨appdomain调用并访问Thread.CurrentThread。也许线程具有特殊的跨appdomain语义,可以传递。我想值得一试。顺便说一句,CLR有一个非托管的探查器API,它可能可以做你想做的事情。
return new TransactionController(this, transactionMode, isolationLevel);
if (th == Thread.CurrentThread)
                throw new NextException("Internal error: it seems the thread {0} once called BeginWork() is the same thread which calls GetThreadWorks() now...", th.ManagedThreadId);
pragma warning disable 612, 618
            th.Suspend();
            var trace = new StackTrace(th, details == StackDetalization.Detailed);
            th.Resume();
pragma warning restore 612, 618
            var sb = new StringBuilder();
            int frameCount = trace.FrameCount;
            for (int i = 0; i < frameCount; i++)
            {