作用
在使用.NET編寫的代碼在debug時很容易進行排查和定位問題,一旦項目上線並出現問題的話那么只能依靠系統日志來進行問題排查和定位,但當項目復雜時,即各種方法間相互調用將導致要獲取具體的出錯方法或調用者將是一件不那么容易的事(因為沒有PDB文件)
還好.NET提供了一系列系統組件來幫助我們獲取項目堆棧信息用於定位和排查,以下代碼將返回出錯 堆棧調用的各上一級方法,直到最終的調用者方法
入棧的過程

棧是一個先進后出(FILO)的結構,在從圖上很容易就明白了,堆棧幀的定義了,即main()方法在調用時需要在棧上保存的一些數據所對應的內存就是main的堆棧幀,同理methodA()方法對應的就是methodA的堆棧幀了。
使用StackFrame和StackTrace類 獲取當前函數名,當前代碼行,源代碼文件
StackTrace st = new StackTrace(new StackFrame(true));只能獲取本函數的堆棧信息,可以改用下面的方法獲取程序的調用堆棧信息。
StackTrace st = new StackTrace(new StackFrame(1,true));只能獲取調用本函數的函數的堆棧信息,可以改用下面的方法獲取程序的調用堆棧信息。
StackTrace st = new StackTrace(true); 就可以獲取程序的整個堆棧調用關系的列表信息
堆棧的跟蹤依依賴於.pdb文件。如果沒有.pdb文件將無法輸出源代碼中的文件路徑和行號、列號。
案例
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { //只能獲取本函數的堆棧信息,可以改用下面的方法獲取程序的調用堆棧信息。 StackTrace st = new StackTrace(new StackFrame(true)); Console.WriteLine(" Stack trace for current level: {0}", st.ToString()); StackFrame sf = st.GetFrame(0); Console.WriteLine(" File: {0}", sf.GetFileName()); Console.WriteLine(" Method: {0}", sf.GetMethod().Name); Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber()); Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber()); Console.WriteLine("------------------------------------------------"); SayHello(); } static void SayHello() { //只能獲取調用本函數的函數的堆棧信息,可以改用下面的方法獲取程序的調用堆棧信息。 StackFrame stackFrame = new StackTrace(new StackFrame(1,true)).GetFrame(0); Console.WriteLine("Hello~"); Console.WriteLine(" Stack trace for current level: {0}", stackFrame.ToString()); Console.WriteLine("File Name: {0}", stackFrame.GetFileName()); Console.WriteLine("Method Name: {0}", stackFrame.GetMethod().Name); Console.WriteLine("Line Number: {0}", stackFrame.GetFileLineNumber()); Console.WriteLine("Column Number: {0}", stackFrame.GetFileColumnNumber()); } } }
StackFrame stackFrame = new StackFrame(1, true);中1的意思了,就是指在堆棧幀中跳過的幀數,沒錯!!因為StackFrame stackFrame = new StackFrame(1, true);是在SayHello()方法中定義的所以,跳過1幀就跟蹤到了調用main()的地方了