Mat*_*ski 4 .net 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);
Run Code Online (Sandbox Code Playgroud)
哪里applications.Count = 3.上面的代码执行后,我得到了forEachResult.Count = 2和testForEachPassResult.Count = 3
为什么forEachResult集合不包含所有元素?没有例外ParallelLoopResult.IsCompleted = true.
解决我的问题可能有帮助的一件事是这三个项目是在两个线程下运行的:
我认为你的使用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);
}
});
Run Code Online (Sandbox Code Playgroud)
请注意,如果您这样做,那么值的顺序forEachResult将不符合项目的顺序applications.如果你想要那么你必须使用ParallelLoopState类的索引.
| 归档时间: |
|
| 查看次数: |
2940 次 |
| 最近记录: |