这是使用Parallel.ForEach()线程安全吗?
基本上,我正在使用这个:
var data = input.AsParallel(); List output = new List(); Parallel.ForEach(data, line => { String outputLine = ""; // ** Do something with "line" and store result in "outputLine" ** // Additionally, there are some this.Invoke statements for updating UI output.Add(outputLine); });
输入是List
对象。 ForEach()
语句对每个值执行一些处理,更新UI,并将结果添加到output
List
。 这有什么本质上的错误吗?
笔记:
更新:
根据我得到的反馈,我在output.Add
语句以及UI更新代码中添加了手动lock
。
是; List
不是线程安全的,因此从任意线程(很可能同时)ad-hoc添加它是注定的。 您应该使用线程安全列表,或手动添加锁定。 或者也许有一个Parallel.ToList
。
此外,如果重要:不保证插入订单。
但这个版本是安全的:
var output = new string[data.Count]; Parallel.ForEach(data, (line,state,index) => { String outputLine = index.ToString(); // ** Do something with "line" and store result in "outputLine" ** // Additionally, there are some this.Invoke statements for updating UI output[index] = outputLine; });
这里我们使用index
来更新每个并行调用的不同数组索引。
这有什么本质上的错误吗?
是的,一切。 这些都不安全。 列表并不安全地同时更新多个线程,并且您无法从UI线程以外的任何线程更新UI。
文档说明了以下关于List
的线程安全性:
此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。 任何实例成员都不保证是线程安全的。
List(Of T)可以同时支持多个读者,只要不修改集合即可。 枚举集合本质上不是线程安全的过程。 在枚举与一个或多个写访问争用的极少数情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。 要允许多个线程访问集合以进行读取和写入,您必须实现自己的同步。
因此, output.Add(outputLine)
不是线程安全的,您需要自己确保线程安全,例如,通过将add操作包装在lock
语句中。
上述就是C#学习教程:这是使用Parallel.ForEach()线程安全吗?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1008075.html