在c#方法中获取stacktrace

时间:2016-05-08 17:03:01

标签: c# logging callstack

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

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

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

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

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

还有其他解决方案吗?

1 个答案:

答案 0 :(得分:4)

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

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

这样的事情:

  

在System.Environment.GetStackTrace(Exception e,Boolean needFileInfo)
     在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;
}