Search code examples
c#multithreadinginvokeinvokerequired

C# Questions regarding Invoke, Invokerequired & Multithreading


I have 2 forms running on different threads. Form2 will generate a string, send it back to form1 and update the richtextbox in form1. I got the code from my friend but I don't understand a part of it.

Could you please explain to me why do we need the condition:

if (this.f1_rtb_01.InvokeRequired) { }

And what do 2 lines below do?

SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });

Full Code Form1:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;

namespace PassingData2Forms
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public string str_1;

    private void call_form_2()
    {
        for (int i = 0; i < 10; i++)
        {
            Form2 inst_form2 = new Form2();
            inst_form2.ShowDialog();

            string result = inst_form2.SelectedString;
            this.SetText(result);
        }
    }

    delegate void SetTextCallback(string text);

    private void SetText(string text)
    {
        if (this.f1_rtb_01.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            if (text != "")
            {
                this.f1_rtb_01.AppendText(text + Environment.NewLine);
            }
            else
            {
                this.f1_rtb_01.AppendText("N/A" + Environment.NewLine);
            }
        }
    }

    private void f1_but_01_Click(object sender, EventArgs e)
    {
        Thread extra_thread_01 = new Thread(() => call_form_2());
        extra_thread_01.Start();            
    }
}
}

Solution

  • This part:

    SetTextCallback d = new SetTextCallback(SetText);
    this.Invoke(d, new object[] { text });
    

    causes the current form to invoke an instance of the SetTextCallback delegate, passing the variable text as a parameter. The delegate instance points to the SetText() method, which will, due to calling this.Invoke(), be executed on the same thread as the form.

    Invocation is used to move the execution of code from a background thread to a form's/control's thread, thus making the execution thread-safe.

    This part is just for checking if you are required to invoke:

    if (this.f1_rtb_01.InvokeRequired)
    

    If you aren't required to invoke that means that the code already runs on the form's or control's thread, and will throw an exception if you try to invoke.