我已经用Parallel.For替换了代码中的for循环。性能提升非常惊人(1/3的运行时间)。我尝试使用数组来收集结果代码来说明共享资源。然后,我在Parallel.For外部处理数组。这是最有效的方式吗?或者即使没有迭代可以共享相同的循环索引,阻塞仍然会发生吗?CompareExchange会有更好的表现吗?
int[] pageResults = new int[arrCounter];
Parallel.For(0, arrCounter, i =>
{
AlertToQueueInput input = new AlertToQueueInput();
input.Message = Messages[i];
pageResults[i] = scCommunication.AlertToQueue(input).ReturnCode;
});
foreach (int r in pageResults)
{
if (r != 0 && outputPC.ReturnCode == 0) outputPC.ReturnCode = r;
}发布于 2015-05-20 19:08:54
这取决于你在主循环中是否有任何(有价值的)副作用。
当outputPC.ReturnCode是唯一的结果时,你可以使用PLINQ:
outputPC.ReturnCode = Messages
.AsParallel()
.Select(msg =>
{
AlertToQueueInput input = new AlertToQueueInput();
input.Message = msg;
return scCommunication.AlertToQueue(input).ReturnCode;
})
.FirstOrDefault(r => r != 0);这里假设scCommunication.AlertToQueue()是线程安全的,并且您不希望在出现第一个错误后为其余的项调用它。
请注意,PLinq中的FirstOrDefault()只是有效的in Framework 4.5 and later。
发布于 2015-05-20 18:41:28
您可以替换:
foreach (int r in pageResults)
{
if (r != 0 && outputPC.ReturnCode == 0) outputPC.ReturnCode = r;
}通过以下方式:
foreach (int r in pageResults)
{
if (r != 0)
{
outputPC.ReturnCode = r;
break;
}
}这将在第一次失败时停止循环。
发布于 2015-05-20 18:51:41
我喜欢David Arno的解决方案,但正如我所见,您可以通过将检查放入并行循环中并直接从并行循环中中断来提高速度。无论如何,如果任何一次迭代失败,您都会让主代码失败,因此不需要进一步的迭代。
如下所示:
Parallel.For(0, arrCounter, (i, loopState) =>
{
AlertToQueueInput input = new AlertToQueueInput();
input.Message = Messages[i];
var code = scCommunication.AlertToQueue(input).ReturnCode;
if (code != 0)
{
outputPC.ReturnCode = code ;
loopState.Break();
}
});更新1:
如果你需要保存所有迭代的结果,你可以这样做:
int[] pageResults = new int[arrCounter];
Parallel.For(0, arrCounter, (i, loopState) =>
{
AlertToQueueInput input = new AlertToQueueInput();
input.Message = Messages[i];
var code = scCommunication.AlertToQueue(input).ReturnCode;
pageResults[i] = code ;
if (code != 0 && outputPC.ReturnCode == 0)
outputPC.ReturnCode = code ;
});它将把你从foreach循环中解救出来,虽然这是一个很小的改进。
更新2:
刚刚发现了这个post,我认为自定义并行也是一个很好的解决方案。但这是你的决定,它是否适合你的任务。
https://stackoverflow.com/questions/30346774
复制相似问题