Parallel.For维护输出列表上的输入列表顺序

时间:2012-06-30 10:31:40

标签: c# list parallel-processing webforms

我想在重载操作期间保持列表顺序的一些输入,我决定以并行方式尝试以确定它是否会提升性能。 (确实如此!)

我提出了一个解决方案,但由于这是我第一次尝试任何平行的事情,如果我做了一些非常愚蠢的事情,我需要有人拍我的手。

有一个查询返回一个卡片所有者列表,按名称排序,然后按出生日期排序。这需要在网页上的表格中呈现(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。

1 个答案:

答案 0 :(得分:1)

一点代码审查:

  • 应删除对Dispose()的2次调用。充其量它们是无害的。
  • 仔细研究如何获得originalIndex。它应该总是等于i,所以你不需要它。

但除了这一点精简之外,没有太多改进。令人怀疑的是,并行执行此操作会有很大帮助,或者这是您代码中的真正瓶颈。我怀疑大部分时间都花在处理TableRow[]的结果上。