是否可以捕获并重试内部clr异常?

时间:2019-09-11 21:01:57

标签: c# exception .net-core

在调用.ToArray时,出现以下异常:

Internal CLR error. (0x80131506)
at System.Linq.Enumerable.ToArray[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)

这是间歇性发生的,很难重现。可以捕获并重试这种类型的异常吗?我只需要捕获一个通用异常即可。

调用.ToArray()的代码在异步Task中。在异步代码之外已经有一个常规的try / catch来捕获任何异常并将其记录下来。似乎并没有找到该代码(未打印日志消息这一事实证明了这一点)

不幸的是,我没有一个很好的可重现的小例子。如果我有一个,我可能可以调试并找出问题所在。可能有1%的时间发生。

通用结构如下:

private async Task<bool> Foo()
{
    try
    {
      return (await Bar()).Value;
    }
    catch (Exception e)
    {
       LogError();
       return false;
    }
}

private async Task<bool> Bar()
{
    // workQueue uses an ActionBlock to run tasks
    var tasks = workToDo.Select(item => await workQueue.ProcessItem(item, DoWorkOnItem));
    await Task.WhenAll(tasks);
}

async Task<bool> DoWorkOnItem(Item i)
{
    var convertedStatements = i.Select(s => ConvertStatement(s, context)).Where(s => s != null).ToList();
    var statementArray = ConvertedStatement.FlattenStatements(convertedStatements).ToArray(); // This is where the exception is hit
}

public static IList<Statement> FlattenStatements(ICollection<ConvertedStatement> convertedStatements)
{
    Contract.Requires(convertedStatements != null);

     var result = new List<Statement>(convertedStatements.Count);
     foreach (var statement in convertedStatements)
     {
         // m_statement is only set in the constructor of Statement
         if (statement.m_statement != null)
         {
             result.Add(statement.m_statement);
         }
         else
         {
             // m_statements is a read-only list of Statement, only set in the constructor of Statement
             result.AddRange(statement.m_statements);
         }
     }

     return result;
}

我应该在排队的任务中添加一个try catch吗?当它打印内部CLR错误的完整异常时,该跟踪不包含Foo(),它将向上抛出以下操作块:

 at BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ProcessWorkItem(QueueInput`1<Boolean,Boolean>)
 at System.Threading.Tasks.Dataflow.ActionBlock`1[[BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1+QueueInput`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], BuildXL.FrontEnd.Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6212d9137135ce5d]].ProcessMessageWithTask(System.Func`2<QueueInput`1<Boolean,Boolean>,System.Threading.Tasks.Task>, System.Collections.Generic.KeyValuePair`2<QueueInput`1<Boolean,Boolean>,Int64>)
 at System.Threading.Tasks.Dataflow.ActionBlock`1+<>c__DisplayClass6_1[[BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1+QueueInput`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], BuildXL.FrontEnd.Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6212d9137135ce5d]].<.ctor>b__2(System.Collections.Generic.KeyValuePair`2<QueueInput`1<Boolean,Boolean>,Int64>)
 at System.Threading.Tasks.Dataflow.Internal.TargetCore`1[[BuildXL.FrontEnd.Sdk.SourceFileProcessingQueue`1+QueueInput`1[[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], BuildXL.FrontEnd.Sdk, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6212d9137135ce5d]].ProcessMessagesLoopCore()
 at System.Threading.Tasks.Task.InnerInvoke()
 at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
 at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread)
 at System.Threading.ThreadPoolWorkQueue.Dispatch()

这使我认为try catch应该位于DoWorkOnItem中,而不是Foo中。听起来不错吗?

1 个答案:

答案 0 :(得分:0)

这似乎是合法的内部错误。如果您搜索错误代码,则会发现此错误的实例,然后由Microsoft进行修复。

  

可以捕获并重试内部clr异常吗?

我很好奇,您尝试过吗?结果如何?

这不是FileNotFoundException,您可能正确地认为可以重试。这是有问题的,因为您不知道CLR /执行引擎的内部状态有多严重。重试可能会给您带来另一个异常,或者仅仅是错误的结果。

简而言之,如果您使用的是最新版本,则正确的做法可能是将其报告给Microsoft。