Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异常调用堆栈被截断,没有任何重新抛出_C#_.net_Exception_Stack Trace_Stack Frame - Fatal编程技术网

C# 异常调用堆栈被截断,没有任何重新抛出

C# 异常调用堆栈被截断,没有任何重新抛出,c#,.net,exception,stack-trace,stack-frame,C#,.net,Exception,Stack Trace,Stack Frame,我有一个不寻常的例子,我有一个非常简单的异常被抛出并在同一个方法中捕获它不会被重新抛出(这是天真的程序员通常遇到的问题)。但它的StackFrame只包含当前方法中的一个。下面是它的样子: at (my class).MyMethod() in C:\(my file path and line) 实际上,在VS2010调试器的调用堆栈中,可能有30个方法可以实现这一点,它们跨越六个不同的程序集。所有这些似乎都不可能被优化。此外,对于.NET 4,此代码是在调试模式下构建的,没有优化。我

我有一个不寻常的例子,我有一个非常简单的异常被抛出并在同一个方法中捕获它不会被重新抛出(这是天真的程序员通常遇到的问题)。但它的StackFrame只包含当前方法中的一个。下面是它的样子:

   at (my class).MyMethod() in C:\(my file path and line)
实际上,在VS2010调试器的调用堆栈中,可能有30个方法可以实现这一点,它们跨越六个不同的程序集。所有这些似乎都不可能被优化。此外,对于.NET 4,此代码是在调试模式下构建的,没有优化。我甚至在同一文件夹中有(基于).ini文件(包括名为[app].vshost.ini的文件),其中包含:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
而且,方法调用不在方法的末尾,因此尾部递归优化似乎不太可能

至于如何调用它:在调用堆栈上没有使用反射,没有任何形式的Invoke()或BeginInvoke()。这只是一个按钮点击的长串调用。单击处理程序在调用堆栈中大约有10个调用。下面是常见的WndProc、NativeWindow.Callback、本机/托管转换和消息循环。这最终是在从C#EXE程序集运行的ShowDialog()调用中实现的

现在,我发现我可以在catch处理程序中构造StackTrace类的实例,如果我传递Exception对象,调用堆栈也很短。如果我只调用new StackTrace(),而不带任何参数,则会生成一个完整的调用堆栈

我曾尝试使用Reflector调试抛出的异常类及其调用堆栈的内部,但我无法在Exception或StackTrace中设置断点。我可以在Environment.GetStackTrace()中设置它们,这个方法(异常调用)在构造和抛出过程中似乎没有被调用,但我不知道调试器是否真的工作正常。(不过,这个方法确实会在其他一些情况下触发,所以我不确定该如何使用它。)

以下是该方法的摘录:

private void MyMethod()
{
    ...               
    try
    {
        throw new ApplicationException("Test failure");
    }
    catch (Exception e)
    {
        StackTrace stackTrace1 = new StackTrace(e);
        StackTrace stackTrace2 = new StackTrace(e, false);
        StackTrace stackTrace3 = new StackTrace(e, true);
        StackTrace stackTrace4 = new StackTrace();
        string STs = stackTrace1.ToString() + "\n---\n"
            + stackTrace2.ToString() + "\n---\n"
            + stackTrace3.ToString() + "\n---\n"
            + stackTrace4.ToString();
        Log(EventSeverity.Debug, STs);
        ...
        }
    }
它非常简单:抛出异常,捕获并记录它

无论是在调试器中还是在运行单机版(单行调用堆栈)时,我都会得到相同的结果。我知道我在代码库的其他地方看到过这个问题。以前我假设这是由于重新抛出异常,但在很多情况下,我们都会直接在初始catch块中记录。我很困惑,我所做的所有网络搜索都没有产生任何结果


作为对所提供答案的评论,这有点太多了,但这里有更多信息:

我现在看到,这个行为在 事实上,它是在中描述的(尽管我认为人们很容易错过他们在那里说的话)

所以我想我的“解决方案”会有点不着边际。我们通常调用一个中心方法来格式化异常。在该方法中,我将创建一个新的StackTrace(),包括和不包括Exception对象。然后,我将查找位于异常堆栈跟踪底部的方法,并在new StackTrace()中显示该方法下方的所有内容,表明该方法是由该系列调用调用的


当然,不利的一面是,如果不使用此方法,信息将不存在。但是我不得不期望在某个地方发生某种代码更改。

当抛出异常时,
exception.StackTrace
属性中只使用部分堆栈跟踪。堆栈仅在捕获异常的方法之前显示调用。要获得完整的堆栈(如您所述),您应该创建一个
新的StackTrace()
对象

我现在找不到它的任何链接,但我相信堆栈跟踪是通过在抛出异常时向上遍历堆栈而建立的。一旦异常到达catch块,堆栈将停止编译。因此,只能得到部分堆栈


通常,catch块与调用它的人无关,而与异常的来源无关。

重要的是如何调用此方法。例如,通过委托的BeginInvoke()方法。更好地描述它。我同意@Hans Passant(+1)。谢谢,我在上面添加了以下内容:关于如何调用它:调用堆栈上没有反射,没有任何形式的Invoke()或BeginInvoke()。这只是一个按钮点击的长串调用。单击处理程序在调用堆栈中大约有10个调用。下面是常见的WndProc、NativeWindow.Callback、本机/托管转换和消息循环。这最终是在从C#EXE程序集运行的ShowDialog()调用中实现的。它是否在单独的线程上运行?如果在新线程上调用该特定方法,那么调用堆栈可以是1行。你说没有*调用,但那是异步的,那么线程呢?有没有理由不使用Exception.StackTrace属性?啊,这很令人沮丧,但却是正确的。我已经习惯于看到通过我们的系统发送的未处理异常的调用堆栈,以至于我没有注意到当您实际捕获一个异常时会发生这种情况。