这里有一些方法。首先一个简单的Parallel.ForEach
,减少保护区(lock https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement)到所需的绝对最小值(共享状态的更新)。这应该可以最大限度地减少对锁的争用。
DataTable data = this.Db.ExecuteRead(query, this.Score.Name);
double totalTime = 0.0;
Parallel.ForEach(data.AsEnumerable(), row =>
{
double time = Double.Parse(row[0].ToString()) / MillisecondsPerMinute;
lock (data) { totalTime += time; }
});
A PLINQ https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/introduction-to-plinq方法。简单且安全,但可能不是最有效的:
double totalTime = data
.AsEnumerable()
.AsParallel()
.Select(row => Double.Parse(row[0].ToString()) / MillisecondsPerMinute)
.Sum();
的组合Parallel.ForEach
and Partitioner.Create https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.partitioner.create应该提供最佳性能,因为它允许分块工作负载:
double totalTime = 0.0;
Parallel.ForEach(Partitioner.Create(0, data.Rows.Count), () => 0.0D,
(range, state, accumulator) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
DataRow row = data.Rows[i];
accumulator += Double.Parse(row[0].ToString()) / MillisecondsPerMinute;
}
return accumulator;
}, accumulator =>
{
lock (data) { totalTime += accumulator; }
});