英文:
Parallel.ForEach in Web API
问题
以下是翻译好的部分:
"Does the following code run without any problems or side effects?"
"I'm not using a Dictionary, so I do not have any duplicate keys. I just add entries to the List. So, I don't need to use a concurrent collection, do I?"
英文:
Does the following code run without any problems or side effects?
var result = new List<MyTpe>();
Parallel.ForEach(items, i =>
{
// make DB-request
..
result.Add(otherResult);
}
I'm not using a Dictionary, so I do not have any duplicate keys. I just add entries to the List. So, I don't need to use a concurrent collection, do I?
答案1
得分: 0
Your code is not thread safe, so, yes, there could be problems such as overwriting list entries. Also, Add
could cause the list to resize. Imagine if two threads simultaneously triggered that.
你的代码不是线程安全的,所以是的,可能会出现问题,比如覆盖列表条目。此外,Add
可能会导致列表重新调整大小。想象一下,如果两个线程同时触发了它。
You can place a lock
around your accesses to the list, or even better use a concurrent collection such as ConcurrentBag if you don't care about order.
你可以在访问列表时加锁,或者更好的办法是使用并发集合,比如 ConcurrentBag,如果你不关心顺序的话。
Another way to do this is to allocate an array sized to the degree of parallelism on the Parallel.ForEach
and then (safely) put the results into the respective slot. Finally, you'd then assemble the results after the loop.
另一种方法是在 Parallel.ForEach
上分配一个大小与并行度相匹配的数组,然后(安全地)将结果放入相应的槽中。最后,在循环之后汇总结果。
Something like
// this example assumes parallelism is 4
var result = new List<MyTpe>[4];
Parallel.ForEach(items, i =>
{
var localResult = new List<MyType>();
// make DB-request
localResult.Add(otherResult);
...
// n passed in somehow (check the overloads of ForEach()
result[n] = localResult;
}
...
var finalResult = new List<MyType>();
foreach (var r in result)
finalResult.AddRange(r);
英文:
Your code is not thread safe, so, yes, there could be problems such as overwriting list entries. Also, Add
could cause the list to resize. Imagine if two threads simultaneously triggered that.
You can place a lock
around your accesses to the list, or even better use a concurrent collection such as ConcurrentBag if you don't care about order.
Another way to do this is to allocate an array sized to the degree of parallelism on the Parallel.ForEach
and then (safely) put the results into the respective slot. Finally, you'd then assemble the results after the loop.
Something like
// this example assumes parallelism is 4
var result = new List<MyTpe>[4];
Parallel.ForEach(items, i =>
{
var localResult = new List<MyType>();
// make DB-request
localResult.Add(otherResult);
...
// n passed in somehow (check the overloads of ForEach()
result[n] = localResult;
}
...
var finalResult = new List<MyType>();
foreach (var r in result)
finalResult.AddRange(r);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论