6 Replies - 560 Views - Last Post: 26 April 2012 - 09:26 AM Rate Topic: -----

#1 cilaes  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 73
  • Joined: 12-December 11

Progressive updating FOR loop

Posted 24 April 2012 - 01:20 PM

I have a for loop that's ping testing a list of IPs and updating the SubItem in a ListView if the ping was successful or not. The subitems aren't actually added until the loop has finished cycling through all of the listview items... Is there a way to update the statuses on the fly? Maybe my code will clear up my question a bit:

foreach (ListViewItem lvi in this.lvwProxies.Items)
            {
                //ping test first
                ProxyCheck pc = new ProxyCheck(lvi.Text);
                if (pc.PingTest() == true)
                {
                    lvi.SubItems.Add("OK");
                }
                else
                {
                    lvi.SubItems.Add("NOGO");
                }
            }



Is This A Good Question/Topic? 0
  • +

Replies To: Progressive updating FOR loop

#2 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4311
  • View blog
  • Posts: 7,467
  • Joined: 08-June 10

Re: Progressive updating FOR loop

Posted 24 April 2012 - 05:52 PM

I assume you mean that the UI isn't updating until the loop is finished. There are a few ways to handle it. It's been a while since I worked with WinForms, but I believe you can use Application.DoEvents() to allow for a UI update. You could do that at the end of each loop iteration.

That's not really a clean way to do it, though. The best thing would be to use a BackgroundWorker, to perform your task on a background thread, if it's long-running. You can handle the ProgressChanged event to allow for UI updates.
Was This Post Helpful? 2
  • +
  • -

#3 cilaes  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 73
  • Joined: 12-December 11

Re: Progressive updating FOR loop

Posted 25 April 2012 - 08:29 AM

View PostCurtis Rutland, on 24 April 2012 - 05:52 PM, said:

The best thing would be to use a BackgroundWorker, to perform your task on a background thread, if it's long-running. You can handle the ProgressChanged event to allow for UI updates.


Thanks a lot, that was exactly what I was looking for. However I've ran into another problem that I understand what is going on in a way, but can't seem to dig the knowledge out of my head on how to go about it.

My issue that's standing now is when I try to access my List that is created outside of the background worker through a foreach:

foreach (ListViewItem lvi in this.lvwData.Items)


I've read the article How to: Make Thread-Safe Calls to Windows Forms Controls but how exactly can one Invoke a List type? I'm not altering the List, just reading from it.
Was This Post Helpful? 0
  • +
  • -

#4 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4311
  • View blog
  • Posts: 7,467
  • Joined: 08-June 10

Re: Progressive updating FOR loop

Posted 25 April 2012 - 09:03 AM

What you'll want to do is extract the data from your list view before you make the thread call. Try assigning lvwData.Items to a variable, and using that for your call.
Was This Post Helpful? 0
  • +
  • -

#5 cilaes  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 73
  • Joined: 12-December 11

Re: Progressive updating FOR loop

Posted 26 April 2012 - 03:37 AM

View PostCurtis Rutland, on 25 April 2012 - 09:03 AM, said:

What you'll want to do is extract the data from your list view before you make the thread call. Try assigning lvwData.Items to a variable, and using that for your call.


Then how could I update that certain row in the List View? Here's my code:

 private void bgwProxyCheck_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            int totalProxies = lvwProxies.Items.Count;
            double pEachTemp = 100 / totalProxies;
            int percentEach = Convert.ToInt32(Math.Ceiling(pEachTemp));
            int totalChecked = 0;

            //List<string> copyProxies = new List<string>(lstProxies);

            foreach (ListViewItem lvi in this.lvwProxies.Items)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // update status bar.
                    this.tssState.Text = "Checking...";

                    //ping test first
                    ProxyCheck pc = new ProxyCheck(lvi.Text);
                    if (pc.PingTest() == true)
                    {
                        lvi.SubItems.Add("OK");
                        PingVerified.Add(lvi.Text);

                        //sock test second
                        if (pc.SockTest() == true)
                        {
                            lvi.SubItems.Add("OK");
                            txtDebug.Text = txtDebug.Text + lvi.Text + Environment.NewLine;
                        }
                        else
                        {
                            lvi.SubItems.Add("NOGO");
                        }
                    }
                    else
                    {
                        lvi.SubItems.Add("NOGO");
                    }
                }

                totalChecked++;
                
                worker.ReportProgress((percentEach * totalChecked));

            }
        }



Note in the foreach I have foreach(ListViewItem lvi... so that I can lvi.SubItems.Add().. How would I go about doing that if during initialization I added each entry to a List, and then just copied the list in the background worker?

EDIT: I attempted to make a call to .InvokeRequired but it doesn't exist for my ListView control?

This post has been edited by cilaes: 26 April 2012 - 05:06 AM

Was This Post Helpful? 0
  • +
  • -

#6 cilaes  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 73
  • Joined: 12-December 11

Re: Progressive updating FOR loop

Posted 26 April 2012 - 08:53 AM

Okay, so after some tinkering, I know what I was doing wrong. It just made it extremely confusing when it seemed like I could read/write a variable. That wasn't the case.

For anyone that stumbles upon this, my problem was that I was trying to read/write from/to a ListView from inside the DoWork of my backgroundworker. Instead, I had to make a List<string> of each line of data, and read that in on my DoWork section and call a method checking if InvokeRequired like such:

delegate void AddToListCallback(ListViewItem lvi);

private void AddToList(ListViewItem lvi)
        {
            if (this.lvwProxies.InvokeRequired)
            {
                AddToListCallback d = new AddToListCallback(AddToList);
                this.Invoke(d, new object[] { lvi });
            }
            else
            {
                this.lvwProxies.Items.Add(lvi);
            }
        }

Was This Post Helpful? 1
  • +
  • -

#7 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4311
  • View blog
  • Posts: 7,467
  • Joined: 08-June 10

Re: Progressive updating FOR loop

Posted 26 April 2012 - 09:26 AM

You should be doing things like that in your ProgressChanged event, because things that happen there will be run on the UI thread, and you won't have to invoke them yourself. Look up a good backgroundworker tutorial and you'll see how to use ProgressChanged properly.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1