c# - 可以捕获并重试内部 clr 异常吗?
问题描述
在调用 .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() 的代码位于异步任务中。在异步代码之外已经有一个通用的 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 中。听起来对吗?
解决方案
这看起来像是一个合法的内部错误。如果您搜索错误代码,您会发现出现这种情况的实例,然后是 Microsoft 的修复程序。
可以捕获并重试内部 clr 异常吗?
我很好奇,你试过吗?你的结果是什么?
这不是FileNotFoundException
,您可能正确地认为您可以重试。这是有问题的,因为您不知道 CLR/执行引擎的内部状态可能被损坏到何种程度。重试可能会给您带来另一个异常,或者仅仅是不正确的结果。
简而言之,如果您使用的是最新版本,那么正确的做法可能是向 Microsoft 报告。
推荐阅读
- swift - 如何以编程方式将约束添加到两个 UI 项(标签和按钮?
- wildfly - 如何为 elytron 生成掩码密码?
- node.js - NodeJS 创建函数数组并通过 async.series 执行
- c# - 如何在 Razor 视图中使用 foreach 循环显示连接的 sql 列值
- php - 向 loginController 添加逻辑
- math - 为什么 MAPLE 不评估我的方程中的积分和导数?
- r - 使用 R 进行 HTML 抓取 - 抓取特定节点时出错
- android - 如何在可打印区域中平均分隔项目
- android - 如何使滚动视图增长并向上滚动?
- amazon-web-services - 在 aws 中分离实时环境和测试环境的最佳方法