c# – Parallel.ForEach缺少项目
作者:互联网
我有以下代码:
HttpContext httpContext = HttpContext.Current;
RequestContext currentContext = RequestContextManager.CurrentContext;
ILifetimeScope currentSessionScope = PlatformContext.LifeTimeScope;
ConcurrentQueue<Exception> exceptions = new ConcurrentQueue<Exception>();
ConcurrentBag<ParallelCalculateObj> forEachResult = new ConcurrentBag<ParallelCalculateObj>();
ConcurrentBag<ParallelCalculateObj> testForEachPassResult = new ConcurrentBag<ParallelCalculateObj>();
ParallelLoopResult loopResult = Parallel.ForEach(applications, () =>
{
HttpContext.Current = httpContext;
RequestContextManager.SetCustomCurrentContext(currentContext);
PlatformContext.LifeTimeScope = currentSessionScope;
return new ParallelCalculateObj();
}, (application, pls, localObj) =>
{
try
{
// some code
}
catch (Exception e)
{
exceptions.Enqueue(e);
}
testForEachPassResult.Add(localObj);
return localObj;
}, forEachResult.Add);
其中applications.Count = 3.执行上面的代码后,我获得了forEachResult.Count = 2和testForEachPassResult.Count = 3
为什么forEachResult集合不包含所有元素?
没有例外,ParallelLoopResult.IsCompleted = true.
解决我的问题可能有帮助的一件事是这三个项目是在两个线程下运行的:
> Item01 – > Thread.CurrentThread.ManagedThreadId是14
> Item02 – > Thread.CurrentThread.ManagedThreadId是10
> Item03 – > Thread.CurrentThread.ManagedThreadId是14
解决方法:
我认为你以错误的方式使用Parallel.ForEach
.
您正在使用具有本地状态的重载.此本地状态对于分区/线程是唯一的,但并非每个迭代都具有唯一的本地状态.
考虑将输入列表划分为N个分区.然后是N个本地州.作为最后一步,您将这N个本地状态组合成最终值.通常,N将小于列表中的项目数,除非您使用一个更具体的重载,否则TPL将确定列表的分区方式.
由于您显然希望使用每次迭代的结果填充一些列表,因此本地状态也应该是一个列表,其中包含该特定分区的每次迭代的结果.对于最终操作,您将所有列表合并为一个列表:
Parallel.ForEach(
applications,
() => new List<ParallelCalculateObj>(),
(application, pls, localObj) =>
{
// do something
var obj = new ParallelCalculateObj { /* data of the iteration */ };
localObj.Add(obj);
return localObj;
},
localObj =>
{
foreach (var result in localObj)
{
forEachResult.Add(result);
}
});
请注意,如果您这样做,那么forEachResult中的值的顺序将不对应于应用程序中的项目顺序.如果你想要那么你必须使用ParallelLoopState类的索引.
标签:c,net,parallel-foreach-2 来源: https://codeday.me/bug/20190612/1224957.html