Search code examples
c#winformsbackgroundworkertask-parallel-librarymultitasking

process listview in background using tasks


I have the following code:

    private void _DoValidate(object sender, DoWorkEventArgs e)
    {
        this.BeginInvoke(new MethodInvoker(() =>
        {
            Parallel.ForEach
                (this.listView2.CheckedItems.OfType<ListViewItem>(),
                new ParallelOptions { MaxDegreeOfParallelism = 4 },
                (item) =>
                {
                    List<string> data = new List<string>();
                    for (int s = 1; s < 5; s++)
                    {
                        if (item.SubItems[s].Text != null)
                            data.Add(item.SubItems[s].Text);
                        else
                            data.Add("");
                    }
                    this.BeginInvoke((Action)(delegate()
                    {
                        bool verified = checkdata(data);
                        item.Checked = verified;
                    }));
                });
        }));
    }

which is working but it is updating the gui after all tasks are completed. I added a backgroundworked to be able to use the gui while the tasks are running.

How can I make this function to update the listviewitems as soon as they are verified not in the end?


Solution

  • I think your problem is that you just queue everything on the UI thread. I don't know what exactly this line does

    this.BeginInvoke(new MethodInvoker(() =>
    

    but looks like it runs something on the UI thread.

    The Parallel.ForEach also runs on the UI thread, eventually forking into some worker threads that call

    this.BeginInvoke((Action)(delegate()
    

    again - which is just queuing work on the UI thread, which won't get executed until the Parallel.ForEach method returns(it waits for all its worker threads to finish first) but it also runs on the UI thread !

    What I would suggest is to run the Prallel.ForEach on a worker thread either by using BackgroundWorker or by just calling Task.Factory.StartNew.