在C#中向ListView添加项目太慢

4

我希望向列表视图控件添加项目。以下是一段代码:

    this.lView.ListViewItemSorter = null;
    ListViewItem[] lvitems = new ListViewItem[ListMyObjects.Count];
    int index = 0;
    foreach (MyObject object in ListMyObjects)
        {
            ListViewItem item = new ListViewItem();               
            item.Text = object.Name;
            lvitems[index++] = item;
        }
    this.lView.BeginUpdate();
    this.lView.Items.AddRange(lvitems); // Slow in here with debugger
    this.lView.EndUpdate();

我只添加了大约1000个项目,但速度非常慢。它需要大约15秒才能完成。有人知道原因吗?提前感谢。

编辑:

我之前已经定制了listview。

public partial class MyListView: ListView
{        
    public MyListView()
    {
        InitializeComponent();
        this.View = View.Details;
        this.FullRowSelect = true;
        this.DoubleBuffered = true;
    }
    private bool mCreating;
    private bool mReadOnly;
    protected override void OnHandleCreated(EventArgs e)
    {
        mCreating = true;
        base.OnHandleCreated(e);
        mCreating = false;
    }
    public bool ReadOnly
    {
        get { return mReadOnly; }
        set { mReadOnly = value; }
    }
    protected override void OnItemCheck(ItemCheckEventArgs e)
    {
        if (!mCreating && mReadOnly) e.NewValue = e.CurrentValue;
        base.OnItemCheck(e);
    }   
}

我这样做是因为我不想在使用多线程时出现挂起的情况。但我不知道这会对它产生什么影响?


1
哪一行是慢的部分?(使用调试器) - SLaks
1
我尝试使用整数值,速度可接受(<2秒)。也许与你的对象有关? - Matthias
可能是如何加速向ListView添加项目?的重复问题。 - Cody Gray
3个回答

3
你可以通过启用虚拟模式使其更快,虚拟模式可以提升性能,但需要一定的工作量。

你知道这种行为的原因吗?正如我在问题中所评论的,它对整数运作良好。 - Matthias
@Slaks,强制垃圾回收器在foreach循环内运行。我认为在GC自动运行之前,内存中有太多的对象。您可能需要添加以下代码行:GC.Collect(); GC.WaitForPendingFinalizers(); - Bishnu Paudel
@BishnuPaudel:那样做毫无益处;循环中没有任何要收集的东西。 - SLaks

2
添加多个项目的首选方法是使用 AddRange() 方法。但是,如果必须逐个添加项目,可以在循环周围使用 BeginUpdate() 和 EndUpdate() 方法。以下内容来自 MSDN:
“向 ListView 添加多个项的首选方法是使用 ListView.ListViewItemCollection 的 AddRange 方法(通过 ListView 的 Items 属性访问)。这使您能够一次性将数组中的项目添加到列表中。但是,如果您想使用 ListView.ListViewItemCollection 类的 Add 方法逐个添加项目,则可以使用 BeginUpdate 方法防止每次添加项目时控件重新绘制 ListView。”

0

如果您的领域对象很大,这可能会导致瓶颈(根据评论,听起来它们可能正在减速)。 抵歉,这是一种更具体系结构的解决方案。在进入表示层之前,您可以将它们展平为一些(非常简单的)领域传输对象(DTO):只是一堆getter和setter。

AutoMapper这样的工具可能会消除其中很多苦力活

这样,您的领域对象保留在业务逻辑领域中(其所属位置),而表示层仅从DTO获取所需的数据。

抱歉提供一个非基于代码的建议 :) 祝你好运!


请问您能否解释一下“大型”对象与您的DTO(=[POCO's|http://en.wikipedia.org/wiki/Plain_Old_CLR_Object)有何不同?这些属性只是一堆引用吗? - toong
抱怨:所以评论系统没有预览,我需要收集更多的积分才能编辑/修复自己的评论?耶... - toong
一个DTO只发送足以支持一个依赖系统的数据,而POCO可能包含了许多其他数据。通常情况下,POCO在系统内部使用,而DTO在两个系统之间使用(一个系统可以是物理实体或逻辑实体)。希望这能有所帮助,很抱歉评论系统给你带来了困扰。 - user1105802
1
感谢您的澄清,但这只与您的数据需要序列化和反序列化有关吗?循环遍历对象列表对于大型对象并不会更慢,因为它仅仅是一组引用! - toong
这取决于里面有什么 - 如果域对象是10个整数,69个字符串,12个双精度和49个复杂对象,则将其压缩为DTO可能是值得的。如果它只包含一个get/set int,那么可能不值得 :) +1 - user1105802

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接