Csharp/C#教程:这是使用Parallel.ForEach()线程安全吗?分享


这是使用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

(0)
上一篇 2021年12月29日
下一篇 2021年12月29日

精彩推荐