Michael Tucker Michael Tucker - 1 month ago 14
C# Question

How can I run two processes for different listview values in the same listview box?

I'm working on a bigger program, but the operation it does for each value in a listbox takes a long time. I want to speed this up by performing the same process for multiple values in the same listviewbox, basically trying to add some type of Parallel operation logic to get the job done.

I created a quick program that is a very very simple version of the bigger program I'm working in, I'm hoping someone can constructively point me in the right direction.

Is there a way with a listviewbox that I can start at the top and the bottom of a list simultaneously and have each one work their way until they meet in the middle? I can't wrap my head around another way to do this.

Here's example 'code' of what I'm doing now with a background worker, nothing fancy (again, this is a mocked up program because of the "complexity" of the actual program I'm working on.)

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

ListViewItem lst = listView1.SelectedItems[0];

foreach (ListViewItem user in listView1.Items)
{
MessageBox.Show(user.SubItems[0].Text);
}

}

private void button1_Click(object sender, EventArgs e)
{
CheckForIllegalCrossThreadCalls = false; // I know, but this is an example program, so I'm using this for ny own sanity sake right now.
backgroundWorker1.RunWorkerAsync();
}


Here's the GUI part of the program

enter image description here

I hope this makes sense. If not, I can elaborate further, but this is the gist of what I'm trying to do.

(I have tried looking on stack overflow for similar questions, but I haven't found that helps me because they're either in different languages Or they go on a tangent that I can't follow because it's beyond the scope of my program and I don't understand how to adapt their answers to my program.)

UPDATE W/ ANSWER

In the event this helps anyway in the future, I took the advice in the comments and implemented
Parallel.ForEach
in my code. Because it's a listview, I had to be a little more creative with my approach.

My ForEach statement looks like this now:

var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.50) * 1.0)) };

Parallel.ForEach<ListViewItem>(lstBackupUsers.Items.Cast<ListViewItem>(),opts, name => { // Long stuff to do here });


Basically, I removed the regular "foreach" command in my backgroundworker task and replaced it with the Parallel.ForEach above. For reference, I had to use the ParallelOptions to limit the amount of resources (in this case, 50% of my resources.)

Answer

You won't need the Background-Worker for this task. As gilmishal mentioned in comment you can use a Parallel.Foreach. This Class is inside the Task Namespace which holds the new async TAP Pattern from Microsoft. If you use Multithreading you should take a look at this namespace. The Parallel.Foreach starts you action within the method body in a new Thread (if this is sensefull). So you don't need to start at top and bottom. The loop starts for every element of your list at nearly the same time (parallel).

Parallel.ForEach(username, row => { // do your long running stuff });

UDPATE:

Parallel.ForEach is not executed in extra Thread by default. So the UI can freeze. For avoiding this behaviour you should run the Parallel.ForEach in an extra Task. This article points out why you shouldn't run a Parallel.ForEeach in a UI Thread. So for stop freezing UI do following:

 private void button1_Click(object sender, EventArgs e)
 {
    Task.Factory.StartNew(() => {
        Parallel.ForEach(username, row => { // background_dowork stuff here? });    
    });
 }

Make sure you don't access any UI Components in the separated thread.

Comments