3

Can anybody tell me how if and else statements are related in this function. I am displaying text from another thread to GUI thread. What's the order or way of execution. Is the else statement necessary?

delegate void SetTextCallback(string text);

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.textBox7.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox7.Text = text;
        }
    }
Daniel Kelley
  • 7,191
  • 5
  • 39
  • 48
user1903439
  • 1,791
  • 5
  • 17
  • 28
  • Without your `else`, the program is very likely to crash, that is because you cannot change the GUI from a foreign thread. Since you need to change the GUI anyways, you `Invoke` the method instead. Without `else`, the foreign thread will attempt to change the GUI right after invoking the method (leading to the crash I mentioned before). `InvokeRequired` checks if the object belongs to the current thread or not, basically it means that `this.textBox7.Text = text;` will never run on any thread other than the one to which `textBox7` belongs. – Nolonar Feb 05 '13 at 10:04

4 Answers4

4
  1. The other thread calls SetText
  2. Since it is not the thread that created the Form it requires Invoke.
  3. this.Invoke calls SetText with the given parameter again. Also check this
  4. Now SetText is called from the UI thread and there is no need to Invoke
  5. in else block we are sure text is set thread safely
Community
  • 1
  • 1
Mehmet Ataş
  • 9,857
  • 5
  • 42
  • 70
2

InvokeRequired is used to check whether the statements are executed in the main UI thread or in an other thread than UI thread.

If the statements are being executed in an other thread than UI thread, Invoke is used to not to cause any CrossThread exception.

daryal
  • 14,035
  • 4
  • 35
  • 54
2

The else is definitely necessary.

What this code does is allow you to safely call SetText from any thread. If you call it from a thread other than the UI thread (if block) it transparently forwards the call to the UI thread (else block), which is the only one that can access the control to read or set its text.

Blindly going for this.textBox7.Text will cause an exception if not done on the UI thread.

Jon
  • 396,160
  • 71
  • 697
  • 768
1

Just to add to the other answers, this is a common pattern (especially in scenarios where the called method contains a fair amount of logic) - calling back into the same method from the UI thread if InvokeRequired returns true:

private void SetText(string text)
{
    if (InvokeRequired)
        BeginInvoke(new Action<string>((t) => SetText(text)));
    else
        textBox7.Text = text;
}

That way you do not have to repeat your logic in both the if and else.

Daniel Kelley
  • 7,191
  • 5
  • 39
  • 48