从其他线程更新GUI

时间:2013-01-26 23:01:13

标签: c# .net multithreading

我正在尝试从另一个线程更新列表框,实现此目的的最简单方法是什么?

我尝试了调用文本框,但它没有用。

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();
}

3 个答案:

答案 0 :(得分:1)

您可以使用Control.Invoke来获取UI线程,然后更新列表框。

但是,我建议您使用BackgroundWorker

答案 1 :(得分:1)

我会使用BackgroundWorker,您可以在DoWork中执行异步内容,使用bgworker.ReportProgress()报告您的进度,然后您将在ProgressChanged中收到回调(我会为每个已处理的元素调用ReportProgress,然后您就可以更新GUI控件了。

工作人员也可以在结束时解雇RunWorkerCompleted

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";
}

请记住,您的背景工作者必须在WorkerReportProgress属性中生效。

答案 2 :(得分:1)

您需要使用Dispatcher.BeginInvoke。您可以查看this链接,以便更好地了解如何从不同的线程更新UI控件。 例如,如果列表框名为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]) });
}