在不使用Parallel.ForEach()的测试中,将处理3500条记录。
但是通过并行处理,每次尝试处理的记录数量都会减少。(3402、3375、3471等)我发现DBSet不支持并行编程,所以我将项目移到列表中,然后再处理列表。(不理想)一些丢失的记录作为空对象添加到列表中。
我遗漏了什么?
public int Execute(CalculateAutoClassRatesCommandRequest request)
{
int recordCount = 0;
var autoClassCalculations = new List<AutoClassCalculation>();
var options = new ParallelOptions { MaxDegreeOfParallelism = 2 };
Parallel.ForEach(request.BaseCalculations, options, baseCalculation =>
{
foreach (var autoClass in request.AutoClasses
.Where(autoClass => baseCalculation.BaseClassId == autoClass.BaseClassId)
.Where(autoClass => autoClass.AutoClassForms != null))
{
foreach (var form in autoClass.AutoClassForms)
{
recordCount++;
var calcRate = CreateAutoClassCalculation(autoClass.AutoClassRoundingRules, form, baseCalculation);
autoClassCalculations.Add(calcRate);
}
}
});
foreach (var autoClassCalculation in autoClassCalculations)
{
request.AutoClassCalculationsDbSet.Add(autoClassCalculation);
}
request.ratingContext.SaveChangesWithChangeTracking(request.Identity);
return recordCount;
}
private static AutoClassCalculation CreateAutoClassCalculation(
IEnumerable<AutoClassRoundingRule> autoClassRoundingRules,
AutoClassForm autoClassForm,
BaseCalculation baseCalculation)
{
var autoClassCalculation = new AutoClassCalculation()
{
BaseCalculation = baseCalculation,
AutoClassForm = autoClassForm,
BaseCalculationId = baseCalculation.BaseCalculationId,
AutoClassFormId = autoClassForm.AutoClassFormId
};
var roundingRule = autoClassRoundingRules != null ? autoClassRoundingRules.FindMatchingAutoClassRoundingRule(autoClassForm.AutoClassId, autoClassCalculation.CalcRate) : new AutoClassRoundingRule();
autoClassCalculation.CalculateRate(roundingRule);
return autoClassCalculation;
}发布于 2013-09-09 14:05:54
我在您的代码中看到了一个问题和一个潜在的问题:
所有线程都直接访问recordCount变量。虽然num++看起来像一个原子操作,但它不是。它本质上等同于num = num + 1。由于这是在多个CPU指令中执行的,所以线程有可能在更新值之前获得一个值并被挂起。同时,其他线程会增加该值,并且一旦恢复初始线程,它只会将它根据旧的起始值计算出来的值放置起来。您应该使用Interlocked.Increment()函数,而不是使用递增运算符。
Interlocked.Increment(ref recordCount);集合的枚举数可能不是线程安全的。如果您使用的是自定义集合类型,则对元素的并行访问可能比预期的速度更快。不过,这不应该引起你所描述的问题。明智的做法是使用BlockingCollection。
https://stackoverflow.com/questions/18699849
复制相似问题