【问题标题】:Get stacktrace inside c# method在 c# 方法中获取堆栈跟踪
【发布时间】:2016-09-03 07:15:03
【问题描述】:

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

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

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

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

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

还有其他解决办法吗?

【问题讨论】:

  • 你当然可以破解它:抛出一个异常,捕获它并从中读取调用堆栈:)
  • @MarcinJuraszek 不错的 hack :) 但我担心它会影响性能太多。

标签: c# logging callstack


【解决方案1】:

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

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

类似这样的:

在 System.Environment.GetStackTrace(异常 e,布尔需要文件信息)
在 System.Environment.get_StackTrace()
在 WpfApplication2.MainWindow.GetStack(Int32 removeLines)
在 WpfApplication2.MainWindow.Button_Click(对象发送者,RoutedEventArgs e)
...
在 System.Threading.ThreadHelper.ThreadStart()

您需要做的就是拆分/解析/格式化它,无论您想用它做什么。

由于您将在自己的课程中使用它,请记住删除最新的 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;
}

【讨论】:

  • 请注意,.net 对于不同的语言有不同的堆栈跟踪输出,因此在删除“at”和其他语言相关的单词时需要小心。
  • 好主意。我会将其包含在答案中以供将来参考。
猜你喜欢
  • 2010-09-11
  • 2011-06-01
  • 2010-10-11
  • 1970-01-01
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多