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

tip*_*nes 5 c# user-interface multithreading

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

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 ???
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我再次开始新鲜,所以我不会搞砸我的代码.如果有人想用我的例子提出一个很好的例子.

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

J.D*_*.D. 6

Invoke或BeginInvoke,例如

Invoke((MethodInvoker)delegate {
    MainForm.UpdateTextBox("Hello World"); 
});
Run Code Online (Sandbox Code Playgroud)

@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"); 
    }
}
Run Code Online (Sandbox Code Playgroud)

当你对此感到满意时,你可以阅读lambda表达式,并执行以下操作:

Thread testThread = new Thread(() => t.HelloWorld(this));
Run Code Online (Sandbox Code Playgroud)


SLa*_*aks 5

您可以调用该BeginInvoke方法,该方法会将委托排队以在 UI 线程上异步执行。

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

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


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