C# Parallel.ForEach缺少项
我有以下代码:C# Parallel.ForEach缺少项,c#,.net,parallel.foreach,C#,.net,Parallel.foreach,我有以下代码: HttpContext httpContext = HttpContext.Current; RequestContext currentContext = RequestContextManager.CurrentContext; ILifetimeScope currentSessionScope = PlatformContext.LifeTimeScope; ConcurrentQueue<Exception> exceptions = new Concur
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);
HttpContext-HttpContext=HttpContext.Current;
RequestContext currentContext=RequestContextManager.currentContext;
ILifetimeScope currentSessionScope=平台上下文.LifeTimeScope;
ConcurrentQueue exceptions=新建ConcurrentQueue();
ConcurrentBag forEachResult=新ConcurrentBag();
ConcurrentBag testForEachPassResult=新ConcurrentBag();
ParallelLoopResult loopResult=Parallel.ForEach(应用程序,()=>
{
HttpContext.Current=HttpContext;
RequestContextManager.SetCustomCurrentContext(currentContext);
PlatformContext.LifeTimeScope=当前会话范围;
返回新的并行计算bj();
},(应用程序,pls,本地对象)=>
{
尝试
{
//一些代码
}
捕获(例外e)
{
例外情况。排队(e);
}
testForEachPassResult.Add(localObj);
返回localObj;
},forEachResult.Add);
其中applications.Count=3
。执行上述代码后,我得到了forEachResult.Count=2
和testForEachPassResult.Count=3
为什么forEachResult集合不包含所有元素?
没有异常,ParallelLoopResult.IsCompleted=true
有一件事可能有助于解决我的问题,那就是这三项是在两个线程下运行的:
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);
}
});
Parallel.ForEach(
应用,
()=>新列表(),
(应用程序,pls,本地OBJ)=>
{
//做点什么
var obj=新的并行计算bj{/*迭代的数据*/};
localObj.Add(obj);
返回localObj;
},
localObj=>
{
foreach(localObj中的var结果)
{
forEachResult.Add(结果);
}
});
请注意,如果这样做,则
forEachResult
中的值顺序将与应用程序中的项目顺序不一致。如果需要,那么必须使用ParallelLoopState
类的索引。有3种方法,其中两种已经提到过
(1) 每个循环创建一个集合并将其结果添加到此任务结果集合。完成后,将合并所有任务结果。我将使用它作为默认值,因为if避免了锁争用
(2) 在所有任务之外创建公共集合。所有任务都写入集合,但写入此集合(添加项)必须与锁同步,因为它不是原子的。如果只有100个项目需要处理,但每个项目的处理时间为1秒或更长,我会使用此选项。在这种情况下,锁定时间可以忽略不计
(3) 在所有任务之外创建一个数组,并为每个任务指定一个区域来写入结果。即使所有任务都写入同一个数组,它们写入的内存位置也不同。因此不需要同步
示例(3)
//源必须是数组或IList。
var source=Enumerable.Range(0,100000).ToArray();
//对整个源阵列进行分区。
var rangePartitioner=Partitioner.Create(0,source.Length);
double[]结果=新的double[source.Length];
//并行地在分区上循环。
Parallel.ForEach(rangePartitioner,(range,loopState)=>
{
//在没有委托调用的情况下在每个范围元素上循环。
对于(int i=range.Item1;i
代码来源:这就是我使用System.Collections.Concurrent命名空间的原因。这是线程安全的。非常感谢!但是你能给我解释一下使用localFinally部分的目的吗?我不能在循环体中将项添加到集合中吗?@MateuszPuwałowski localFinally将每个分区的结果合并成一个最终值。以问题为例:您有两个分区,第一个分区包含Item01和Item03,第二个分区包含Item02。这两个本地列表包含处理Item01和Item03的结果以及Item02的结果。localFinally步骤然后将这两个列表合并为一个包含所有三个结果的列表。
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);
}
});
// Source must be array or IList.
var source = Enumerable.Range(0, 100000).ToArray();
// Partition the entire source array.
var rangePartitioner = Partitioner.Create(0, source.Length);
double[] results = new double[source.Length];
// Loop over the partitions in parallel.
Parallel.ForEach(rangePartitioner, (range, loopState) =>
{
// Loop over each range element without a delegate invocation.
for (int i = range.Item1; i < range.Item2; i++)
{
results[i] = source[i] * Math.PI;
}
});