在 c# 方法中获取堆栈跟踪

Get stacktrace inside c# method

我想实现通用记录器,它可以帮助我查看方法的调用堆栈。

我知道 System.Diagnostic 中有一些方法,但它们是在 .net 4.0 中引入的,恐怕它不适用于 xamarin 或 .net core 或类似的东西。所以我想有更通用的解决方案。

另一个问题是 async\await,它引入了一些混乱。

我通过在每个方法中传递附加参数来存储一些上下文并帮助我确定调用堆栈,但是这个解决方案有点复杂。

我也可以使用不安全代码读取线程堆栈内存并自行检查调用堆栈,但它不可靠。

还有其他解决办法吗?

您可以直接使用 Environment.StackTrace。这从一开始就是框架的一部分。

Environment.StackTrace 将 return 完整的堆栈跟踪(包括对 Environment.StackTrance 本身的调用)作为行分隔的字符串。

像这样:

at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
at System.Environment.get_StackTrace()
at WpfApplication2.MainWindow.GetStack(Int32 removeLines)
at WpfApplication2.MainWindow.Button_Click(Object sender, RoutedEventArgs e)
...
at System.Threading.ThreadHelper.ThreadStart()

您只需 split/parse/format 它,随心所欲。

由于您将在自己的 类 中使用它,请记住删除最新的 X 行。

这段代码应该可以在任何地方使用,因为它是故意设计的低级代码。

private static string[] GetStack(int removeLines)
{
    string[] stack = Environment.StackTrace.Split(
        new string[] {Environment.NewLine},
        StringSplitOptions.RemoveEmptyEntries);

    if(stack.Length <= removeLines)
        return new string[0];

    string[] actualResult = new string[stack.Length - removeLines];
    for (int i = removeLines; i < stack.Length; i++)
        // Remove 6 characters (e.g. "  at ") from the beginning of the line
        // This might be different for other languages and platforms
        actualResult[i - removeLines] = stack[i].Substring(6);

    return actualResult;
}