-1

I am trying to update my listview in a windows forms application that processes a text file updates the control. My problem is cross-threading related; whenever I try to update the control an error arises. There were no errors before I multi-threaded the application, however the UI would only update once the entire text file was processed. I would like the UI to update after each line is read.

I have posted the related code, hopefully someone can give me some tips because I am at a wall right now. The error occurs during the if statement in the UpdateListView method. Note the PingServer method is one that I have written, and is unrelated to my question.

    private void rfshBtn_Click(object sender, EventArgs e)
    {
        string line;
        // Read the file and display it line by line.
        var file = new StreamReader("C:\\Users\\nnicolini\\Documents\\Crestron\\Virtual Machine Servers\\servers.txt");
        while ((line = file.ReadLine()) != null)
        {
            Tuple<string, string> response = PingServer(line);
            Thread updateThread = new Thread(() => { UpdateListView(line, response.Item1, response.Item2); });
            updateThread.Start();
            while (!updateThread.IsAlive) ;
            Thread.Sleep(1);
        }
        file.Close();
    }

    private void UpdateListView(string host, string tries, string stat)
    {
        if (!listView1.Items.ContainsKey(host)) //if server is not already in listview
        {
            var item = new ListViewItem(new[] { host, tries, stat });
            item.Name = host;
            listView1.Items.Add(item); //add it to the table
        }
        else //update the row
        {
            listView1.Items.Find(host, false).FirstOrDefault().SubItems[0].Text = host;
            listView1.Items.Find(host, false).FirstOrDefault().SubItems[1].Text = tries;
            listView1.Items.Find(host, false).FirstOrDefault().SubItems[2].Text = stat;
        }
    }
Nick Nicolini
  • 129
  • 1
  • 3
  • 14
  • 1
    You need to check if the control is being invoked, and then call it from the underlying thread. Check this out http://stackoverflow.com/a/12179408/752527 – Hanlet Escaño Jun 18 '13 at 21:53
  • 1
    *Lots* of existing resources about this, if you just search: http://stackoverflow.com/search?q=cross-thread+%5Bwinforms%5D+%5Bc%23%5D – Peter Ritchie Jun 19 '13 at 01:19

1 Answers1

1

Winform components can be updated only from the main thread. If you want to do the update form other thread, updating code should be invoked on the main thread using component.BeginInvoke().

Instead of

 listView1.Items.Add(item);

You can write something like:

listView1.BeginInvoke(() => listView1.Items.Add(item));

If your thread is doing only UI updates and nothing else resource intensive, then it is reasonable not to use it at all and call UpdateListView as a method from the main thread.

alex
  • 12,464
  • 3
  • 46
  • 67