我有一个ConcurrentBag集合,对于其中的每个项目,我都会做一些工作。
我知道带有ConcurrentBag的Parallel.ForEach是线程安全的,但我从未以这种方式进行并行处理。
我的代码看起来像这样
public void Work(IList<MyModel> data)
{
var tasks = new ConcurrentBag<Task>();
var safeData = new ConcurrentBag<MyModel>(data);
foreach (var item in safeData )
{
var task = Task.Factory.StartNew(() => SomeTask(item));
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
}
那么,这段代码是线程安全的吗?
谢谢
编辑:
也许这个问题可能是:“item”是线程安全的还是可以在两次迭代之间更改其值?
编辑2:
如果此代码可能属于problem,我将引用a。
编辑3:
在此question中,“理智的元子”直接使用循环变量时会遇到问题。我认为可以使用ConcurrentBag纠正此问题,但是在某些答案中,请告诉我我根本不需要ConcurrentBag。所以:
一个好主意是直接使用循环变量吗?
建议何时将值复制到另一个变量?
直接与ConcurrentBag中的循环变量一起使用是否安全?
最佳答案
除了现有的答案:
问题不在于多线程或并发。关于closures。
foreach
,则取决于您的编译器版本。如果使用旧版本编译代码,则会导致问题,如that very question中所述。如果使用for
循环,则应始终复制循环变量。有关更多详细信息,请参见Jon's answer中的链接。 ConcurrentBag
不会影响结果。如果您使用的编译器版本比
4.0.30319.1
更旧(对于MS编译器),则关闭循环变量是安全的。 More info about compiler versions。 同样,如对该问题的评论中所述,您可以使用静态分析工具来突出显示这种情况。