Toddams
Toddams

Reputation: 1499

I can update UI from background thread, why?

Everybody knows, that updating UI from background thread is not allowed (or not?)

I did a little experiment. Here is a piece of code:

var thread = new Thread(() => progressBar1.Increment(50));
            thread.IsBackground = true;
            thread.Start();
            thread.Join();

I put this code in some button click handler. And know what? My progressbar is incrementing...From background thread. And now I am confused. I don't understand how it is possible and what am I doing wrong

Upvotes: 6

Views: 1203

Answers (3)

Eric Lippert
Eric Lippert

Reputation: 659956

Everybody knows, that updating UI from background thread is not allowed

Not everyone knows that. But it is true. Updating most UI elements from threads other than the UI thread is wrong.

I don't understand how it is possible

You pour a bunch of sand into your car's oil sump. You're not supposed to do that. So how is it possible that you just did so? Seems like a strange question to ask, doesn't it?

Is the car required to stop you from doing so? No. Is it required that the engine stops running when you do so? No. Will the engine break eventually? Probably. But not necessarily.

The engineers who designed your car assumed that you would not do something so wrong, so they did not build in any safety systems to prevent or detect this problem.

what am I doing wrong?

You're updating the UI from a background thread. Don't do that. But the runtime is not required to provide a safety system that prevents or detects your error. It is not required to produce an error when you do something that you shouldn't be doing in the first place. It can do so if it wants, or not, at its discretion.

Or, think about it this way. Suppose you were implementing the runtime so that it had the property you thought it had: that the runtime will always detect bad cross-thread calls and produce an error when they happen. That's a feature. Someone has to design, write, test, and maintain that code. What does the code look like, and what are all the costs associated with it?

Upvotes: 5

Marco Luongo
Marco Luongo

Reputation: 387

Like varocarbas says any component you put into your designer will throw Cross thread exception.

to access between thread you need to use invke, beginInvoke.

try to run

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s1,e1) => 
{
    textBoxt1.Text = "foo";  // Exception here
} 
bw.RunWorkerCompleted += (1s, e1) =>
{
    textBoxt1.Text = "foo";  // No exception here off UI thread
}
bw.RunWorkerAsync();

instead replace

bw.DoWork += (s1,e1) => 
{
    this.Invoke((MethodInvoker) delegate 
   {
        textBoxt1.Text = message;
   });  // No Exception now
} 

Upvotes: -1

Ivan Stoev
Ivan Stoev

Reputation: 205539

I can update UI from background thread, why?

Most probably you can do that when running outside the debugger. This is because that protection is controlled by the Control.CheckForIllegalCrossThreadCalls Property. Let take a look at reference source

private static bool checkForIllegalCrossThreadCalls = Debugger.IsAttached;
public static bool CheckForIllegalCrossThreadCalls {
    get { return checkForIllegalCrossThreadCalls; }
    set { checkForIllegalCrossThreadCalls = value; }
}

As you may see, this protection is enabled by default only when you are debugging.

If you add the following line in your Main method (before Application.Run)

Control.CheckForIllegalCrossThreadCalls = true;

your code will not work anymore.

Upvotes: 8

Related Questions