如何从另一个线程更新主线程中的文本框?

时间:2010-12-15 01:53:44

标签: c# multithreading user-interface

如何从运行不同类的新线程更新主线程中的文本框和标签。

MainForm.cs(主线程)

public partial class MainForm : Form
{
    public MainForm()
    {
        Test t = new Test();

        Thread testThread = new Thread(new ThreadStart(t.HelloWorld));
        testThread.IsBackground = true;
        testThread.Start();
    }

    private void UpdateTextBox(string text)
    {
        textBox1.AppendText(text + "\r\n");
    }

}

public class Test
{
    public void HelloWorld()
    {
        MainForm.UpdateTextBox("Hello World"); 
        // How do I execute this on the main thread ???
    }
}

我看过这里的例子,但似乎无法做到正确。请有人给一些好的链接。

我已经重新开始,所以我不会搞砸我的代码。如果有人想用我的例子提出一个很好的例子。

此外,如果我不得不更新多个对象,如文本框和标签等(不是所有的同时),最好的方法是什么,为每个文本框设置一个方法,或者有办法做到这一点一种方法?

3 个答案:

答案 0 :(得分:6)

Invoke或BeginInvoke,例如

Invoke((MethodInvoker)delegate {
    MainForm.UpdateTextBox("Hello World"); 
});

@tiptopjones我想你也在问如何获得对表单的引用。您可以使HelloWorld方法获取对象参数,使用ParameterizedThreadStart委托,然后将对表单的引用作为参数传递给Thread.Start方法。但我建议阅读有关匿名方法的内容,这些方法可以让它变得更容易,并且可以保存所有强类型内容。

public class MainForm : Form {
    public MainForm() {
        Test t = new Test();

        Thread testThread = new Thread((ThreadStart)delegate { t.HelloWorld(this); });
        testThread.IsBackground = true;
        testThread.Start();
    }

    public void UpdateTextBox(string text) {
        Invoke((MethodInvoker)delegate {
            textBox1.AppendText(text + "\r\n");
        });
    }
}

public class Test {
    public void HelloWorld(MainForm form) {
        form.UpdateTextBox("Hello World"); 
    }
}

当你对此感到满意时,你可以阅读lambda表达式并按照:

进行操作
Thread testThread = new Thread(() => t.HelloWorld(this));

答案 1 :(得分:4)

您可以调用BeginInvoke method,它将队列一个委托在UI线程上异步执行。

如果你需要后台线程等到UI线程上的函数完成,你可以改为调用Invoke

请注意,您需要对表单实例的引用;您应该将其传递给Test构造函数并将其存储在私有字段中。


BackgroundWorker component将使用ReportProgress方法自动完成所有这些操作;你应该考虑使用它。

答案 2 :(得分:1)

WinForms中的首选方法是使用SynchronizationContext

public partial class MainForm : Form
{
    SynchronizationContext ctx;

    public MainForm()
    {
        ctx = SynchronizationContext.Current;

        Test t = new Test();

        Thread testThread = new Thread(new ThreadStart(t.HelloWorld));
        testThread.IsBackground = true;
        testThread.Start();
    }

    private void UpdateTextBox(string text)
    {
        ctx.Send(delegate(object state)
        {
            textBox1.AppendText(text + "\r\n");

        },null);
    }    
}

public class Test
{
    public void HelloWorld()
    {
        MainForm.UpdateTextBox("Hello World"); 
        // How do I excute this on the main thread ???
    }
}