c# - Parallel.Foreach - NULL 任务

标签 c# task-parallel-library task parallel.foreach

我正在努力学习如何使用 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/

相关文章:

c# - 上下文已被处理。执行异步

c# - 在Google Play商店中提交 “500 No individual errors”的原因

c# - MessageBox 是桌面模态的

c# - 是否可以将 LPWSTR 从 C++ DLL 返回到 C# 应用程序

multithreading - 如何在没有主线程等待的情况下从长时间运行的后台任务引发异常

c# - 如何正确编写自定义任务返回方法

具有队列触发的 Azure WebJob 多次触发

c# - Task.Run a void 方法和 Task 方法返回 null 有区别吗?

c# - 无法将类型 'void' 隐式转换为 'System.Threading.Tasks.Task'

c# - 等待的任务能否在 IsCompleted 中返回 false