c# - Parallel.ForEach 失败并显示“对象引用未设置为对象的实例”。例外
问题描述
非常简单Parallel.ForEach
的调用有时会失败
你调用的对象是空的。
图书馆某处而不是我的代码中的异常。这是堆栈跟踪。
at System.Threading.Tasks.TaskReplicator.Run[TState](ReplicatableUserAction`1 action, ParallelOptions options, Boolean stopOnFirstFailure)
at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.Tasks.Parallel.ThrowSingleCancellationExceptionOrOtherException(ICollection exceptions, CancellationToken cancelToken, Exception otherException)
at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
...
它很少发生,我在 Linux 上的 .NET Core 2.1 应用程序上只看到过几次,没有明显的原因,也无法重现。
这是我的简化代码:
var chunkSize = 100;
var processingList = new List<int>();
// removed code here which fill the processing list with data. No nulls here for sure
Parallel.ForEach(
ChunkIndexes(processingList.Count, chunkSize),
(interval) =>
{
var worker = new MyWorker();
worker.Process(processingList, interval.startIndex, interval.endIndex);
});
// Function called by Parallel.ForEach()
public static IEnumerable<(int startIndex, int endIndex)> ChunkIndexes(int totalCount, int chunkSize)
{
for (var i = 0; i < totalCount; i += chunkSize)
{
yield return (i, Math.Min(i + chunkSize, totalCount));
}
}
中的代码Parallel.ForEach
正在处理列表的不同部分,并且仅修改值但不以任何方式更改列表大小。没有异步/等待代码,没有文件访问,也没有网络调用。它看起来很简单,我只是无法弄清楚它是如何因任何原因而失败的。有任何想法吗?
解决方案
基于我自己代码中 Parallel.ForEach 的其他用途、失败堆栈跟踪和下面的评论,我做了一个小的代码更改。到目前为止一切看起来都不错。
基于您的 StackTrace 和 TaskReplicator.Run 的源代码,选项为 null 或复制器的 _pendigReplicas – Peter Csala 8 月 27 日 14:48
以下是在极少数情况下可能会失败的原始源代码:
Parallel.ForEach(
ChunkIndexes(processingList.Count, chunkSize),
(interval) => {... code here ... });
修改后的代码。仅添加了 ParallelOptions 参数:
Parallel.ForEach(
ChunkIndexes(processingList.Count, chunkSize),
new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount },
(interval) => {... code here ... });
原始问题仅在 Linux 上运行使用 .net core 2.1 编译的 C# 代码时观察到。
推荐阅读
- vuejs2 - 错误:找不到模块 'nanoid/non-secure'
- vba - 如何在允许您访问其方法的变量中保存对由 `querySelectorAll` 匹配的项目的引用?
- java - Junit5 LauncherDiscoveryRequestBuilder selectPackage 找不到测试
- r - 后续:为 data.frame 中的每个 id 值创建错误消息
- android - 将插件应用于 Gradle KTS 项目失败
- r - 识别直方图中的点
- asp.net-mvc - ASP.NET MVC 中的模型缺少定义错误
- java - 使用邻接表检查有向图是否强连接
- python - 如何通过 Python 中的值访问键?
- flutter - 如何允许延迟关键字?