【问题标题】:.NET - Exception stack trace lines erased on generic methods.NET - 在通用方法上擦除异常堆栈跟踪行
【发布时间】:2012-02-24 19:40:10
【问题描述】:

(最初的内容被删掉了,因为我发现它无关紧要)

我的应用程序有一个通用的 RESTful HTTP 客户端,它将操作包装在 委托并传递给我的 WrapOperation 方法(如下所示)。

但是,当引发异常时,堆栈跟踪仅包含一个条目:

at MyProject.Client.RestClient.WrapOperation[T](String method, String path, Object requestObject, RestOperation`1 action) in D:\{fileName}\RestClient.cs:line 196

我已将问题代码简化为:

private T WrapOperation<T>(String method, String path, Object requestObject, RestOperation<T> action) {

        HttpWebRequest request;
        RestTransaction txn = CreateRequest(method, path, requestObject, out request);

        ////////////////////////////

        try {

            throw new WebException("testing stack trace 6");
            throw new Exception("testing stack trace 7");

            using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {

                txn.GotResponse( response );

                return action( txn, response );
            }

        } catch(WebException wex) {
            // NOTE: When exceptions are caught, they're missing the first few entries of the stack trace
            // And appear as though "WrapOperation[T]" (sic) is the entrypoint. Why is this?


            if( wex.Response != null ) {

                HttpWebResponse response = (HttpWebResponse)wex.Response;

                txn.GotResponse( wex, response );

                CopyResponseToMemoryStream( response, txn ).Dispose();

            } else {

                txn.GotResponse( wex );
            }

            // NOTE: However, when these RestExceptions are caught (by WrapOperation's caller), their stack trace is complete and shows the entire trace
            throw new RestException("WebExeption during GetResponse.", txn, wex );

        } catch(Exception ex) {

            txn.GotResponse( ex );

            // NOTE: However, when these RestExceptions are caught (by WrapOperation's caller), their stack trace is complete and shows the entire trace
            throw new RestException("Non-WebException during GetResponse.", txn, ex );
        }

    }

当“testing stack trace 6”异常被抛出时,当被catch(WebException wex)捕获时,wex的堆栈跟踪只包含一个条目。

这是为什么?

【问题讨论】:

  • 异常代码实际上是什么样的?您是在使用 throw ex 还是只是 throw 将异常传递到链中?
  • 你的线程的入口点是什么方法?是 DoAsync(Action) 吗?您能否展示创建、启动和执行异步任务的代码?
  • 您没有发布缺少的中间方法的代码,因此很难猜测。这里至少有两种情况。您只会看到任务执行的方法,异常跟踪是基于线程的。抖动优化器会为内联的小方法生成代码,因此您看不到这些,异常是基于堆栈帧的。使用 [MethodImpl] 抑制该优化。
  • 对不起。在做了一些研究以缩小问题范围后,我已经完全重写了这个问题。

标签: .net winforms generics exception-handling


【解决方案1】:

看起来您将原始异常包装到自定义异常类中。当您读回异常以查看堆栈跟踪时,您还必须检查内部异常行以获取完整的跟踪。

编辑-

堆栈跟踪从抛出异常的地方开始,所以显示的堆栈跟踪是正确的,我原来对问题的描述是正确的。

只要您抛出一个新异常,该异常的堆栈跟踪就会从该点开始。

再次在您的原始示例中,检查此处的内部异常:

//throwing the exception resets the stack trace!
//the next catch will see the exception as coming from this line, and
//will need to look at the inner exception at that point to see the
//original exception! I Think! I have no idea what RestException is,
//only that your passing the original exception ex into it as a parameter.
throw new RestException("Non-WebException during GetResponse.", txn, ex );

【讨论】:

  • 内部异常(在实例化 RestExceptions 时分配)缺少初始堆栈帧 - 我包装异常的事实无关紧要。
【解决方案2】:

如果您的(未显示)方法之一正在捕获异常,然后像这样重新抛出它:

throw ex;

然后堆栈跟踪将被重置为从重新抛出点开始。

throw;

将维护堆栈跟踪。

【讨论】:

    猜你喜欢
    • 2011-01-05
    • 2013-05-24
    • 2017-08-06
    • 2010-09-13
    • 2011-08-10
    • 2018-12-03
    • 1970-01-01
    • 2019-06-30
    相关资源
    最近更新 更多