简体   繁体   中英

How to update textboxes in main thread from another thread?

How you update textboxes and labels in the main thread from a new thread running a different class.

MainForm.cs (Main thread)

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 ???
    }
}

I have looked at the examples on here but cant seem to get it right. Please could someone give some good links.

I have started again fresh so I don't mess up my code. If anyone would like to put up a working example with my example that would be great.

Also if I had to update multiple objects like textboxes and labels etc (not all at the same time) what would be the best way to go about it, having a method for each textbox or is there a way to do this with one method?

Invoke or BeginInvoke, eg

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

@tiptopjones I guess you're asking also how to get a reference to the form. You could make your HelloWorld method take an object parameter, use the ParameterizedThreadStart delegate, and then pass a reference to the form as a parameter to the Thread.Start method. But I would suggest reading about anonymous methods which makes it a lot easier and keeps everything strongly typed.

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

When you get comfortable with that you could read up on lambda expressions and do it like:

Thread testThread = new Thread(() => t.HelloWorld(this));

You can call the BeginInvoke method , which will queue a delegate to be executed asynchronously on the UI thread.

If you need the background thread to wait until the function finishes on the UI thread, you can call Invoke instead.

Note that you will need a reference to the instance of your form; you should probably pass that to the Test constructor and store it in a private field.


The BackgroundWorker component will do all of this automatically using the ReportProgress method; you should consider using it.

The prefered way in WinForms is to use the 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 ???
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM