[英]Parallel.Foreach - NULL Tasks
I'm trying to learn how to use the TPL. 我正在努力学习如何使用TPL。 I've done a fair bit of reading on the subject but I can't understand why the following code sample breaks, and the one after works?
我已经对这个主题做了相当多的阅读,但是我无法理解为什么下面的代码示例会中断,而后面的代码会有效?
I've got a unit test running to count the records wrote, and also reading the outputted file in to double check. 我有一个单元测试运行来计算写入的记录,并且还读取输出的文件以进行双重检查。
Failing: 失败:
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
Working: 工作:
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(...);
});
This use of List<Task> tasks
is not thread-safe. List<Task> tasks
的使用不是线程安全的。 You are seeing null
elements where they shouldn't be but run this a little longer and you may see other symptoms and exceptions as well. 你看到它们不应该是
null
元素,但运行时间稍长,你也可能会看到其他症状和例外。 The behavior is undefined. 行为未定义。
Protect the access to tasks
, replace it with a ConcurrentBag
or, my choice, drop those Tasks altogether. 保护对
tasks
的访问,用ConcurrentBag
替换它,或者我的选择完全放弃这些任务。 You are getting enough parallelism from the Parallel.ForEach()
. 您从
Parallel.ForEach()
获得了足够的Parallel.ForEach()
。
You are seeing a cross-threading issue. 您正在看到一个跨线程问题。
This code block accesses the none-thread safe List<T>
which can lead to unpredictable and none deterministic errors: 此代码块访问非线程安全
List<T>
,这可能导致不可预测且无确定性错误:
tasks.Add(Task.Factory.StartNew(() =>
{
...
}));
You need to lock the tasks.Add call: 您需要锁定任务。添加调用:
lock(tasks)
{
tasks.Add(Task.Factory.StartNew(() =>
{
...
}));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.