如何获取当前C#程序所有线程的调用栈信息 ?
生活随笔
收集整理的這篇文章主要介紹了
如何获取当前C#程序所有线程的调用栈信息 ?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
咨詢區
Daniel Sperry
請問如何獲取 .NET 程序當前所有線程的調用棧信息?我知道在 java 中只需調用 java.lang.Thread.getAllStackTraces() 方法即可。
回答區
Will Calderwood
在 .NET 中并不容易實現,但可以使用診斷庫 ClrMD ,可以在 nuget 上下載,它可以獲取到當前進程的所有線程棧信息的快照,當然還可以獲取 線程名 等各種附加信息,太強大了,參考如下代碼:
using?System.Collections.Generic; using?System.Diagnostics; using?System.Linq; using?System.Text; using?Microsoft.Diagnostics.Runtime;namespace?CSharpUtils.wrc.utils.debugging {public?static?class?StackTraceAnalysis{public?static?string?GetAllStackTraces(){var?result?=?new?StringBuilder();using?(var?target?=?DataTarget.CreateSnapshotAndAttach(Process.GetCurrentProcess().Id)){var?runtime?=?target.ClrVersions.First().CreateRuntime();//?We?can't?get?the?thread?name?from?the?ClrThead?objects,?so?we'll?look?for//?Thread?instances?on?the?heap?and?get?the?names?from?those.????var?threadNameLookup?=?new?Dictionary<int,?string>();foreach?(var?obj?in?runtime.Heap.EnumerateObjects()){if?(!(obj.Type?is?null)?&&?obj.Type.Name?==?"System.Threading.Thread"){var?threadId?=?obj.ReadField<int>("m_ManagedThreadId");var?threadName?=?obj.ReadStringField("m_Name");threadNameLookup[threadId]?=?threadName;}}foreach?(var?thread?in?runtime.Threads){threadNameLookup.TryGetValue(thread.ManagedThreadId,?out?string?threadName);result.AppendLine($"ManagedThreadId:?{thread.ManagedThreadId},?Name:?{threadName},?OSThreadId:?{thread.OSThreadId},?Thread:?IsAlive:?{thread.IsAlive},?IsBackground:?{thread.IsBackground}");foreach?(var?clrStackFrame?in?thread.EnumerateStackTrace())result.AppendLine($"{clrStackFrame.Method}");}}return?result.ToString();}} }點評區
其實是這樣的,如何想自動化獲取當前的進程中所有線程的調用棧,用 ClrMD 即可,如果是為了對程序進行分析診斷,可以借助 windbg,再使用 sos 中的 ~*e !clrstack 命令即可,比如下面這樣:
0:000>?~*e?!clrstack? OS?Thread?Id:?0x4110?(0) Child?SP???????IP?Call?Site 0019f3e4?77a2166c?[InlinedCallFrame:?0019f3e4]? 0019f3e0?79b49b71?DomainNeutralILStubClass.IL_STUB_PInvoke(Microsoft.Win32.SafeHandles.SafeFileHandle,?Byte*,?Int32,?Int32?ByRef,?IntPtr) 0019f3e4?7a27b275?[InlinedCallFrame:?0019f3e4]?Microsoft.Win32.Win32Native.ReadFile(Microsoft.Win32.SafeHandles.SafeFileHandle,?Byte*,?Int32,?Int32?ByRef,?IntPtr) 0019f448?7a27b275?System.IO.__ConsoleStream.ReadFileNative(Microsoft.Win32.SafeHandles.SafeFileHandle,?Byte[],?Int32,?Int32,?Boolean,?Boolean,?Int32?ByRef) 0019f47c?7a27b17b?System.IO.__ConsoleStream.Read(Byte[],?Int32,?Int32) 0019f49c?79b2e6a3?System.IO.StreamReader.ReadBuffer() 0019f4ac?79b2eb5b?System.IO.StreamReader.ReadLine() 0019f4c8?7a3c3786?System.IO.TextReader+SyncTextReader.ReadLine() 0019f4d8?7a221845?System.Console.ReadLine() 0019f4e0?022f0983?***?WARNING:?Unable?to?verify?checksum?for?D:\net5\ConsoleApp1\ConsoleApp1\bin\Debug\ConsoleApp1.exe ConsoleApp1.Program.Main(System.String[])?[D:\net5\ConsoleApp1\ConsoleApp1\Program.cs?@?25] 0019f67c?78e1f036?[GCFrame:?0019f67c]? OS?Thread?Id:?0x11ac?(24) Child?SP???????IP?Call?Site 06c4f214?77a21bdc?[HelperMethodFrame_1OBJ:?06c4f214]?System.Threading.WaitHandle.WaitMultiple(System.Threading.WaitHandle[],?Int32,?Boolean,?Boolean) 06c4f328?79ae8a86?System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[],?Int32,?Boolean) 06c4f34c?7ace3f24?***?WARNING:?Unable?to?verify?checksum?for?C:\Windows\assembly\NativeImages_v4.0.30319_32\System\258d4259dd4377d917679ad4b058966e\System.ni.dll System.Net.TimerThread.ThreadProc() 06c4f3a8?79a62e01?System.Threading.ThreadHelper.ThreadStart_Context(System.Object) 06c4f3b4?79a88604?System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,?System.Threading.ContextCallback,?System.Object,?Boolean) 06c4f420?79a88537?System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,?System.Threading.ContextCallback,?System.Object,?Boolean) 06c4f434?79a884f4?System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,?System.Threading.ContextCallback,?System.Object) 06c4f44c?79a62d5b?System.Threading.ThreadHelper.ThreadStart() 06c4f630?78e1f036?[GCFrame:?06c4f630]? 06c4f774?78e1f036?[DebuggerU2MCatchHandlerFrame:?06c4f774]? OS?Thread?Id:?0x2fdc?(25) Child?SP???????IP?Call?Site 0700f114?755be695?[InlinedCallFrame:?0700f114]? 0700f110?7ad6aa01?DomainBoundILStubClass.IL_STUB_PInvoke(System.Net.SSPIHandle?ByRef,?System.Net.SecurityBufferDescriptor,?UInt32,?UInt32*) 0700f114?7ad530f4?[InlinedCallFrame:?0700f114]?System.Net.UnsafeNclNativeMethods+NativeNTSSPI.DecryptMessage(System.Net.SSPIHandle?ByRef,?System.Net.SecurityBufferDescriptor,?UInt32,?UInt32*) 0700f154?7ad530f4?System.Net.SSPISecureChannelType.DecryptMessage(System.Net.SafeDeleteContext,?System.Net.SecurityBufferDescriptor,?UInt32) 0700f194?7ad51a1a?System.Net.SSPIWrapper.EncryptDecryptHelper(OP,?System.Net.SSPIInterface,?System.Net.SafeDeleteContext,?System.Net.SecurityBuffer[],?UInt32) 0700f1fc?7ad52fe2?System.Net.Security.SecureChannel.Decrypt(Byte[],?Int32?ByRef,?Int32?ByRef) 0700f21c?7ad52e07?System.Net.Security._SslStream.ProcessFrameBody(Int32,?Byte[],?Int32,?Int32,?System.Net.AsyncProtocolRequest) 0700f248?7ad52d6b?System.Net.Security._SslStream.ReadFrameCallback(System.Net.AsyncProtocolRequest) 0700f274?7ad4e576?System.Net.AsyncProtocolRequest.CompleteRequest(Int32) 0700f280?7ad4e537?System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(Int32) 0700f28c?7ad4e4c6?System.Net.FixedSizeReader.ReadCallback(System.IAsyncResult) 0700f2b4?7ad14cf6?System.Net.LazyAsyncResult.Complete(IntPtr) 0700f2e8?7ad49d15?System.Net.ContextAwareResult.CompleteCallback(System.Object) 0700f2ec?79a88604?System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext,?System.Threading.ContextCallback,?System.Object,?Boolean) 0700f358?79a88537?System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,?System.Threading.ContextCallback,?System.Object,?Boolean) 0700f36c?79a884f4?System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext,?System.Threading.ContextCallback,?System.Object) 0700f384?7ad4856d?System.Net.ContextAwareResult.Complete(IntPtr) 0700f39c?7ad14c71?System.Net.LazyAsyncResult.ProtectedInvokeCallback(System.Object,?IntPtr) 0700f3c4?7ad48378?System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32,?UInt32,?System.Threading.NativeOverlapped*) 0700f3f8?79aea3dd?System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32,?UInt32,?System.Threading.NativeOverlapped*) 0700f4f4?78e1f036?[GCFrame:?0700f4f4]? 0700f604?78e1f036?[DebuggerU2MCatchHandlerFrame:?0700f604]? OS?Thread?Id:?0x4214?(26) Child?SP???????IP?Call?Site GetFrameContext?failed:?1 00000000?00000000?0:000>?!tp CPU?utilization:?13% Worker?Thread:?Total:?13?Running:?0?Idle:?13?MaxLimit:?2047?MinLimit:?12 Work?Request?in?Queue:?0 -------------------------------------- Number?of?Timers:?1 -------------------------------------- Completion?Port?Thread:Total:?16?Free:?6?MaxFree:?24?CurrentLimit:?16?MaxLimit:?1000?MinLimit:?12總結
以上是生活随笔為你收集整理的如何获取当前C#程序所有线程的调用栈信息 ?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何从一个 C# 的 dump 中挖到机
- 下一篇: Spring4Shell的漏洞原理分析