1

I'm trying to update a listbox from another thread, what is the simplest way to achieve this?

I tried Invoking the textbox, but it didn't work.

private void dowork()
{
    TcpClient client = new TcpClient();
    client.Connect("192.168.1.3", 10);
    StreamWriter writer = new StreamWriter(client.GetStream());
    StreamReader reader = new StreamReader(client.GetStream());

    JObject o = new JObject();
    o.Add("comando", 1);
    o.Add("dir", @"C:\Users\klein\Desktop\Acionamentos");
    writer.Write(o.ToString());
    writer.Flush();
    JArray array = JArray.Parse(reader.ReadToEnd());
    for (int i = 0; i < array.Count; i++)
    {
        listBox1.Items.Add(array[i]);  //update GUI from this thread
    }
}

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(dowork);
    t.Start();
}
g t
  • 7,287
  • 7
  • 50
  • 85
Bruno Klein
  • 3,217
  • 5
  • 29
  • 39
  • http://stackoverflow.com/questions/2367718/c-automating-the-invokerequired-code-pattern (possible duplicate) – bas Jan 26 '13 at 23:03
  • possible duplicate of [How to update the GUI from another thread in C#?](http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) – AxelEckenberger Jan 27 '13 at 22:58

3 Answers3

1

You can use Control.Invoke to get on UI thread and then update the list box.

However, I suggest you look at using a BackgroundWorker.

Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
1

I would use a BackgroundWorker, you can do your async stuff in DoWork, report your progress using bgworker.ReportProgress() and you will get the callback in ProgressChanged (I would call ReportProgress for every element processed), then you will be able to update your GUI controls.

The worker can also fire RunWorkerCompleted when it ends.

YourType arrayitem;

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    TcpClient client = new TcpClient();
    client.Connect("192.168.1.3", 10);
    StreamWriter writer = new StreamWriter(client.GetStream());
    StreamReader reader = new StreamReader(client.GetStream());

    JObject o = new JObject();
    o.Add("comando", 1);
    o.Add("dir", @"C:\Users\klein\Desktop\Acionamentos");
    writer.Write(o.ToString());
    writer.Flush();
    JArray array = JArray.Parse(reader.ReadToEnd());

    int percentage;

    for (int i = 0; i < array.Count; i++)
    {
        arrayitem = array[i];
        percentage = ((i + 1)*100)/array.Count;
        backgroundWorker1.ReportProgress(percentage);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    listBox1.Items.Add(arrayitem);
    progressBar1.Value = e.ProgressPercentage; // in case you'd want to add a progressbar
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    label1.Text = "Done";
}

Keep in mind your backgroundworker must have true in the WorkerReportProgress property.

Michael Celey
  • 12,645
  • 6
  • 57
  • 62
1

You need to use Dispatcher.BeginInvoke. You can check this link to have better understanding on how to update the UI controls from different thread. For example, if the listbox is named listbox1

for (int i = 0; i < array.Count; i++)
{
    listBox1.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
        new Action(delegate() { listBox1.Items.Add(array[i]) });
}
Michael Celey
  • 12,645
  • 6
  • 57
  • 62
akshayb
  • 76
  • 6