Search code examples
c#listviewbackgroundworker

How to correctly use BackgroundWorker to update ListView? [c# .NET 3.5]


I am trying to use a BackgroundWorker to gather some data for me and update a ListView in my form while i display a progress bar and allow for the gui to not be frozen. I am getting a cross-thread error when i try to update my ListView using the BackgroundWorker. To overcome this, i populate a temporary ListView in the BackgroundWorker and assign it to the result and then use that from the backgroundWorker1_RunWorkerCompleted to populate my original ListView.

#1: Is there a more elegant way to update/display my ListView without having to create another temporary ListView in the _RunWorkerCompleted?

#2: Is there a way to pass the original listview as an argument to the backgroundWorker?

I appreciate any feedback on this.

Thanks in advance!

Pseudo-Code

// 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());
        }
}

Solution

  • To update user interface in cross-thread, you need to Invoke a new Delegate. Check this link here for information on Invoke: Invoke

    Yes you can do that in an elegant way without the need of another temporary listview:

    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);
            }
        }
    }