C# 以线程安全的方式添加到 Parallel.ForEach 循环中的列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17416357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding to a list in a Parallel.ForEach loop in a threadsafe manner
提问by Conor
I have a bit of code that works like this on a list of obj objects called ListofObjects:
我有一些代码可以在名为 ListofObjects 的 obj 对象列表上工作:
List<SomeObject> NewListofObjects<SomeObject>();
Parallel.ForEach(ListofObjects, obj =>
//Do some operations here on obj to get a newobj
NewListofObjects.Add(newobj);
);
Now I am out of the Parallel.ForEach loop, and I want to do an operation on NewListofObjects. However, I get this error when I try to: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt".
现在我退出了 Parallel.ForEach 循环,我想对 NewListofObjects 执行一个操作。但是,当我尝试执行以下操作时出现此错误:“尝试读取或写入受保护的内存。这通常表明其他内存已损坏”。
Is this because my NewListofObjects.Add(newobj) method is not threadsafe? If so, how can I make it threadsafe?
这是因为我的 NewListofObjects.Add(newobj) 方法不是线程安全的吗?如果是这样,我怎样才能使它线程安全?
采纳答案by jason
Is this because my
NewListofObjects.Add(newobj)method is not threadsafe?
这是因为我的
NewListofObjects.Add(newobj)方法不是线程安全的吗?
Correct. It is not threadsafe.
正确的。它不是线程安全的。
Any instance members are not guaranteed to be thread safe.
不保证任何实例成员都是线程安全的。
That's from MSDNreferring to List<T>(scroll to the section titled "Thread Safety").
这是来自MSDN 的引用List<T>(滚动到标题为“线程安全”的部分)。
If so, how can I make it threadsafe?
如果是这样,我怎样才能使它线程安全?
Use a concurrent collection, like ConcurrentBag<T>. Note that you lose the ability to keep track of the order that items were inserted.
使用并发集合,例如ConcurrentBag<T>. 请注意,您无法跟踪项目插入的顺序。
回答by ajawad987
You can use the lockingblock like the following code to insert items into your list in a thread-safe manner.
您可以locking像下面的代码一样使用块以线程安全的方式将项目插入到您的列表中。
var sync = new object();
var myNewList = new List<SomeObject>();
Parallel.ForEach(myListOfSomethings, a =>
{
// Some other code...
var someObj = new SomeObject();
// More other code...
lock(sync)
{
myNewList.Add(someObj);
}
// Even more code...
});
回答by Pa?out
The .NET Framework 4 introduces the System.Collections.Concurrent namespace, which includes several collection classes that are both thread-safe and scalable. https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/
.NET Framework 4 引入了 System.Collections.Concurrent 命名空间,其中包括几个线程安全和可伸缩的集合类。 https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/
BlockingCollection<int>[] sourceArrays = new BlockingCollection<int>[5];
for(int i = 0; i < sourceArrays.Length; i++)
sourceArrays[i] = new BlockingCollection<int>(500);
Parallel.For(0, sourceArrays.Length * 500, (j) =>
{
int k = BlockingCollection<int>.TryAddToAny(sourceArrays, j);
if(k >=0)
Console.WriteLine("added {0} to source data", j);
});

