我想要一些关于在我决定尝试以并行方式执行的重型操作期间保持列表顺序的输入,以查看它是否会提高性能。(它做了!)
我想出了一个解决方案,但由于这是我第一次尝试任何类似的事情,如果我做了一些非常愚蠢的事情,我需要有人拍我的手。
有一个查询返回卡所有者列表,按姓名排序,然后按出生日期。这需要在网页(ASP.Net WebForms)上的表格中呈现。最初的编码人员决定他将逐个单元格 ( TableCell
) 构建表格,将它们添加到行 ( TableRow
) 中,然后将每一行添加到表格中。所以没有GridView,据说它的性能很差,但无论如何性能都很差:)。
数据库查询立即返回,大部分时间花在循环结果和添加表格单元格等上。
我做了以下方法来保持列表的原始顺序:
private TableRow[] ComposeRows(List<CardHolder> queryResult)
{
int queryElementsCount = queryResult.Count();
// array with the query's size
var rowArray = new TableRow[queryElementsCount];
Parallel.For(0, queryElementsCount, i =>
{
var row = new TableRow();
var cell = new TableCell();
// various operations, including simple ones such as:
cell.Text = queryResult[i].Name;
row.Cells.Add(cell);
// here I'm adding the current item to it's original index
// to maintain order in the output list
rowArray[i] = row;
});
return rowArray;
}
List<CardHolder> -> TableRow[]
如您所见,因为我返回的是一种非常不同类型的数据(
此外,我还认为Dispose()
在每个循环结束时对对象进行处理是个好主意,因为查询会返回一个巨大的列表,让单元格和行对象堆积在堆中可能会影响性能。(?)
我做的有多糟糕?如果我的有缺陷,有人有更好的解决方案吗?
经测试,用|2000| 数组,StopWatch
表示并行合成在 63 毫秒(165082 滴答声)内完成,串行合成在 267 毫秒(698222)内完成。两者都包括将行添加到 - ( table.Rows.AddRange()
),然后渲染Table
. 在不添加和渲染的情况下,并行时间为 33ms/87541t,串行时间为 178ms/467068t。