如何正确使用BackgroundWorker更新ListView? [c#.NET 3.5]

时间:2017-08-14 13:36:07

标签: c# listview backgroundworker

我正在尝试使用BackgroundWorker为我收集一些数据并在我的表单中更新ListView,同时显示进度条并允许gui不被冻结。 当我尝试使用BackgroundWorker更新我的ListView时,我收到了一个跨线程错误。为了解决这个问题,我在BackgroundWorker中填充临时ListView并将其分配给结果,然后使用 backgroundWorker1_RunWorkerCompleted 中的那个来填充我原来的ListView。

#1:是否有一种更优雅的方式来更新/显示我的ListView而无需在_RunWorkerCompleted中创建另一个临时ListView?

#2:有没有办法将原始列表视图作为参数传递给backgroundWorker?

我很感激您的任何反馈。

提前致谢!

伪代码

// Original ListView in Form
ListView orginalListView = new ListView();

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    ListView backgroundList = new ListView();
    foreach(var data in database)
    {
        listViewItem = data.value;
        backgroundList.Items.Add(listViewItem);
    }
    e.Result = backgroundList;
}


private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
        // Can I avoid needing to create a temp LV ??
        ListView tempLV = new ListView();
        tempLV = (ListView)e.Result;


        foreach (ListViewItem item in tempLV.Items)
        {
            orginalListView .Items.Add((ListViewItem)item.Clone());
        }
}

2 个答案:

答案 0 :(得分:1)

  

要在跨线程中更新用户界面,您需要调用新的   代表。有关调用的信息,请在此处查看此链接:   Invoke

是的,你可以以优雅的方式做到这一点,而不需要另一个临时列表视图:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (var data in database)
    {
        if (orginalListView.InvokeRequired)
        {
            orginalListView.Invoke(new MethodInvoker(delegate
            {
                listViewItem = data.value;
                orginalListView.Items.Add(listViewItem);
            }));
        }
        else
        {
            listViewItem = data.value;
            orginalListView.Items.Add(listViewItem);
        }
    }
}

答案 1 :(得分:-1)

您可能只需要在线程访问时锁定资源。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    foreach(var data in database)
    {
        listViewItem = data.value;
        String name = "orginalListView";

        lock (((ListView)this.Controls[name]))
        {
            //Update UI, invoked because on different thread.
            Invoke(new MethodInvoker(delegate { ((ListView)this.Controls[name]).Items.Add(listViewItem); }));
        }
     }
}