简体   繁体   English

Parallel.Foreach - NULL任务

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM