为什么在处理操作的方法中catch截断堆栈跟踪?

时间:2022-01-28 19:09:33

Consider this small program. Ignore, if you will, the generic catch, I've kept it brief to try and illustrate the point:

考虑这个小程序。如果你愿意的话,忽略这个普遍的问题,我简短地说明了这一点:

private static void Main(string[] args)
{
    Try(Fail);
}

private static void Fail()
{
    var x = ((string)null).Clone();
}

private static void Try(Action action)
{
    try
    {
        action();
    }
    catch (Exception exc)
    {
        Debug.WriteLine(exc.StackTrace);                
    }
}

When run, the following (with some of the path info removed) is produced:

当运行时,将产生以下内容(删除一些路径信息):

at Scratch.Program.Fail() in Program.cs:line 27
at Scratch.Program.Try(Action action) in Program.cs:line 34

My question is - why does the stack trace of the exception stop unwinding the method chain at the Try() method? I would expect it to unwind past that to the Main() method.

我的问题是-为什么异常的堆栈跟踪停止在Try()方法中展开方法链?我希望它可以unwind到Main()方法。

I haven't been able to find any documentation about what it is that stops exception unwinding going past the Try() - so I'd like to understand this.

我还没有找到任何关于通过Try()停止异常解除的文档——所以我想理解这一点。

2 个解决方案

#1


2  

Exception.Stacktrace calls GetStackTrace which in the end will call
new StackTrace(this /* exception object */, true). When used with these parameters the stack trace will be evaluated for the point of the exception until the current method. You can check that yourself when adding

例外。Stacktrace调用GetStackTrace,最终将调用新的Stacktrace (this /* exception对象*/,true)。当与这些参数一起使用时,堆栈跟踪将被计算为异常点,直到当前方法。您可以在添加时自己检查一下

catch (Exception exc)
{
    Debug.WriteLine(new StackTrace());
    Debug.WriteLine(new StackTrace(exc, true));          
}

The second version is the stacktrace returned by exc.StackTrace, the first is the full stacktrace from the current method to the entry point or thread start.

第二个版本是exc.StackTrace返回的stacktrace,第一个版本是从当前方法到入口点或线程启动的完整stacktrace。

#2


4  

This:

这样的:

try
{
    action();
}
catch (Exception exc)
{
    Debug.WriteLine(exc.StackTrace);                
}

catches your exception inside Try, and doesn't propagate upwards to unwind the callstack, it simply swallows the exception. Therefor, you don't see Main as part of your stacktrace. If you want to see Main, leave the catch to your Main method:

在Try中捕获异常,并没有向上传播以展开调用堆栈,它只是吞掉异常。因此,您不会将Main视为stacktrace的一部分。如果你想看Main,把catch留给你的Main方法:

public static void Main(string[] args)
{
    try
    {
        Try(Fail);
    }
    catch (Exception e)
    {
    }
}

And now you see:

现在你看到的:

at ConsoleApplication2.Program.Fail() in C:\Users\Yuval\documents\visual studio 14\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 25 at ConsoleApplication2.Program.Try(Action action) in C:\Users\Yuval\documents\visual studio 14\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 30 at ConsoleApplication2.Program.Main(String[] args) in C:\Users\Yuval\documents\visual studio 14\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 15

在ConsoleApplication2.Program.Fail()C:\Users\Yuval\documents\visual工作室14 \ ConsoleApplication2 \ ConsoleApplication2 \ \项目计划。cs:ConsoleApplication2.Program第25行。试(Action行动)在C:\Users\Yuval\documents\visual studio 14 \ ConsoleApplication2 \ ConsoleApplication2 \ \项目计划。cs:线在ConsoleApplication2.Program 30。在工作室C:\Users\Yuval\documents\visual Main(String[]args)14 \ ConsoleApplication2 \ ConsoleApplication2 \ \项目计划。cs:第15行

#1


2  

Exception.Stacktrace calls GetStackTrace which in the end will call
new StackTrace(this /* exception object */, true). When used with these parameters the stack trace will be evaluated for the point of the exception until the current method. You can check that yourself when adding

例外。Stacktrace调用GetStackTrace,最终将调用新的Stacktrace (this /* exception对象*/,true)。当与这些参数一起使用时,堆栈跟踪将被计算为异常点,直到当前方法。您可以在添加时自己检查一下

catch (Exception exc)
{
    Debug.WriteLine(new StackTrace());
    Debug.WriteLine(new StackTrace(exc, true));          
}

The second version is the stacktrace returned by exc.StackTrace, the first is the full stacktrace from the current method to the entry point or thread start.

第二个版本是exc.StackTrace返回的stacktrace,第一个版本是从当前方法到入口点或线程启动的完整stacktrace。

#2


4  

This:

这样的:

try
{
    action();
}
catch (Exception exc)
{
    Debug.WriteLine(exc.StackTrace);                
}

catches your exception inside Try, and doesn't propagate upwards to unwind the callstack, it simply swallows the exception. Therefor, you don't see Main as part of your stacktrace. If you want to see Main, leave the catch to your Main method:

在Try中捕获异常,并没有向上传播以展开调用堆栈,它只是吞掉异常。因此,您不会将Main视为stacktrace的一部分。如果你想看Main,把catch留给你的Main方法:

public static void Main(string[] args)
{
    try
    {
        Try(Fail);
    }
    catch (Exception e)
    {
    }
}

And now you see:

现在你看到的:

at ConsoleApplication2.Program.Fail() in C:\Users\Yuval\documents\visual studio 14\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 25 at ConsoleApplication2.Program.Try(Action action) in C:\Users\Yuval\documents\visual studio 14\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 30 at ConsoleApplication2.Program.Main(String[] args) in C:\Users\Yuval\documents\visual studio 14\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 15

在ConsoleApplication2.Program.Fail()C:\Users\Yuval\documents\visual工作室14 \ ConsoleApplication2 \ ConsoleApplication2 \ \项目计划。cs:ConsoleApplication2.Program第25行。试(Action行动)在C:\Users\Yuval\documents\visual studio 14 \ ConsoleApplication2 \ ConsoleApplication2 \ \项目计划。cs:线在ConsoleApplication2.Program 30。在工作室C:\Users\Yuval\documents\visual Main(String[]args)14 \ ConsoleApplication2 \ ConsoleApplication2 \ \项目计划。cs:第15行