在调用.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中。听起来不错吗?
答案 0 :(得分:0)
这似乎是合法的内部错误。如果您搜索错误代码,则会发现此错误的实例,然后由Microsoft进行修复。
可以捕获并重试内部clr异常吗?
我很好奇,您尝试过吗?结果如何?
这不是FileNotFoundException
,您可能正确地认为可以重试。这是有问题的,因为您不知道CLR /执行引擎的内部状态有多严重。重试可能会给您带来另一个异常,或者仅仅是错误的结果。
简而言之,如果您使用的是最新版本,则正确的做法可能是将其报告给Microsoft。