我正在努力学习如何使用 TPL。我已经对这个主题做了很多阅读,但我不明白为什么下面的代码示例会中断,而后面的代码又能正常工作?
我有一个单元测试正在运行以计算写入的记录,并且还读取输出的文件以进行双重检查。
失败:
var tasks = new List<Task>();
Parallel.ForEach(File.ReadLines(featuresLocation), s =>
{
var feature = CreateFeature(s);
if (feature.HasValue)
{
tasks.Add(Task.Factory.StartNew(() =>
{
lock (_locker)
{
featuresWriter.WriteLine(feature.Value);
RecordsWrote++;
}
}));
}
});
Task.WaitAll(tasks.ToArray()); // Breaks
工作:
var tasks = new List<Task>();
Parallel.ForEach(File.ReadLines(featuresLocation), s =>
{
var feature = CreateFeature(s);
if (feature.HasValue)
{
tasks.Add(Task.Factory.StartNew(() =>
{
lock (_locker)
{
featuresWriter.WriteLine(feature.Value);
RecordsWrote++;
}
}));
}
});
Task.WaitAll(tasks.Where(x => x != null).ToArray()); // Works
最佳答案
var tasks = new List<Task>();
Parallel.ForEach(
{
tasks.Add(...);
});
List<Task> tasks
的使用不是线程安全的。你看到的是 null
它们不应该出现的元素,但运行时间稍长,您可能还会看到其他症状和异常。行为未定义。
保护对 tasks
的访问, 将其替换为 ConcurrentBag
或者,我的选择是完全放弃这些任务。您从 Parallel.ForEach()
获得了足够的并行性.
关于c# - Parallel.Foreach - NULL 任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19082756/