Jam
Jam

Reputation: 101

Why “System.InvalidOperationException” not appear?

Sorry for stupid question, but just only started to learn about Threads and Invoke. Why this code execute without any Exceptions:

private void button1_Click(object sender, EventArgs e)
{
    Thread thread = new Thread(DoStuff1);
    thread.Name = "new thread";
    thread.Start();
}

private void DoStuff1()
{
    this.label1.Invoke((MethodInvoker)(() => label1.Text = "info from new thread"));
    button1.BackColor = Color.Red;
    DoStuff2();
}

private void DoStuff2()
{
    label1.Text = "info from new thread";
}

Why body of method DoStuff2 executing, despite on the fact that we trying to change control that has been created by UI thread, from completely another thread. And by the way, if we will make a little changes at method DoStuff2, and will change text, for example to info from new thread2 then Exception appear. Is it some kind of specification of language, it compare texts and if its the same it do nothing? And by the way, why this code execute without Exception button1.BackColor = Color.Red, here we also messing with control on UI thread.

Upvotes: 1

Views: 971

Answers (1)

JonasH
JonasH

Reputation: 36629

To summarize the comments:

Updating UI objects from a background thread is always unsafe:

The Visual Studio debugger detects these unsafe thread calls by raising an InvalidOperationException with the message, Cross-thread operation not valid. Control "" accessed from a thread other than the thread it was created on. The InvalidOperationException always occurs for unsafe cross-thread calls during Visual Studio debugging, and may occur at app runtime. You should fix the issue, but you can disable the exception by setting the Control.CheckForIllegalCrossThreadCalls property to false.

From Make thread-safe calls to Windows Forms controls. Most UI frameworks tend to disallow cross thread calls, so it is not unique to windows forms.

The correct way is to make sure you only update the UI from the main thread. The async/await pattern makes this quite easy as long as you follow the common pattern and do not do anything strange

private void button1_Click(object sender, EventArgs e){
    // Do async call
    var result = await SomeAsyncMethodCall();
    // Update the UI
    myTextbox.Text = result;
}

Upvotes: 3

Related Questions