Parallel.ForEach in Web API

huangapple go评论68阅读模式
英文:

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);

huangapple
  • 本文由 发表于 2023年3月9日 23:53:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687021.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定