【问题标题】:Get real exception type that is contained in AggregateException获取 AggregateException 中包含的真实异常类型
【发布时间】:2017-04-03 11:30:03
【问题描述】:

在具有 59 秒 CancellationToken 的任务中执行数据库查询。如果任务被取消,则抛出 TaskCanceledException。但是这个异常是作为 AggregateException 的一部分被捕获的。 我想提供一个特定的错误消息。那么是否可以在代码中验证 AggregateException 中的真正异常是否是 TaskCancelationException?

【问题讨论】:

  • await 解开 AggregateException 并抛出 InnerExceptions 中的第一个
  • 检查documentation of the class。它展示了如何访问内部异常,将多个聚合异常合并为一个或使用Handle 处理所有内部异常

标签: c# .net exception-handling


【解决方案1】:

你需要使用InnerExceptionInnerExceptions,视你的情况而定:

if (x.InnerException is TaskCanceledException)
{
    // ...
}

如果您知道只有一个例外,上述方法将起作用;但是,如果您有 多个,那么您想对所有这些做一些事情:

var sb = new StringBuilder();

foreach (var inner in x.InnerExceptions)
{
    sb.AppendLine(inner.ToString());
}

System.Diagnostics.Debug.Print(sb.ToString()); 

【讨论】:

    【解决方案2】:

    您可以获取异常列表,如果只有一个,则使用第一个:

    var first = agg.InnerException; // just the first
    
    foreach (Exception ex in agg.InnerExceptions) // iterate over all
    {
        // do something with each and every one
    }
    

    【讨论】:

      【解决方案3】:

      另一种可能的解决方案

      try
      {
          // the logic
      }
      catch (AggregateException e) when (e.InnerException is TaskCancelationException castedException)
      {
          // here castedException is of type TaskCancelationException
      }
      

      https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/when#when-in-a-catch-statement

      【讨论】:

      • 很棒的解决方案。这将消除您在本文和整个代码存储库中看到的复杂异常处理的数百行代码。
      【解决方案4】:

      检查 InnerException 的类型是否有效:

              catch (AggregateException ae)
              {
                  if (ae.InnerException is TaskCanceledException)
                  {
                      LoggerService.Log(LogLevel.Error, "GetReport Request was cancelled");
                      throw ae.InnerException;
                  }
      
                  LoggerService.Log(LogLevel.Error, string.Format("GetReport Request failed: {0}", ae.InnerException.Message));
                  throw;
              }
      

      但是在通过 WCF 通信引发异常之后,它再次被封装在 AggregateException 中。 并且由于某种原因,读取第二种异常类型的机制并不那么容易。但它正在工作:

                      catch (AggregateException ae)
                      {
                          endMessage = string.Format("Defined Query failed. Error: {0}", ae.Message);
      
                          // Set specific error message when TaskCanceledException is contained in AggregateException
                          var fe = ae.InnerException as FaultException<ExceptionDetail>;
                          if (fe != null) if (Type.GetType(fe.Detail.Type) == typeof(TaskCanceledException)) endMessage = "Defined Query was cancelled";
      
                          logLevel = LogLevel.Error;
                          messageType = MessageType.Error;
                      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-11
        • 1970-01-01
        • 2012-12-30
        • 1970-01-01
        • 1970-01-01
        • 2014-12-21
        • 2020-08-05
        • 2021-04-03
        相关资源
        最近更新 更多