3

Possible Duplicate:
Why .NET does not allow cross-thread operations?
Why is only the UI thread allowed to modify the UI?

From what I have understood, the reason .net raises the illegal cross thread calls exception is that the GUI might show indeterministic behaviour.

But isn't this the case with every other object? If two threads work on the same object, depending on the code, the object might be in an indeterministic situation. So why does this exception exist for control elements? Or why is this exception exclusive to control elements.

And how is using invoke going to help? It will still be indeterministic.

Community
  • 1
  • 1
Yamcha
  • 1,264
  • 18
  • 24

3 Answers3

4

Invoke-ing controls on other threads is required because cross-thread calls to Controls are not allowed. For a more complete discussion as to why this restriction exists you should have a read of that link - I'm not going to answer that here, it just is (however be assured that this restriction exists for a good reason).

Calling Invoke helps us because it allows a background thread to "do stuff" on a UI thread - it works because it doesn't directly call the method, rather it sends a Windows message that says "run this when you get the chance to". The UI thread is running a message pump which continuously processes all messages sent to that thread - often these messages are things like "the user clicked on this button", in which case Windows Forms handles this message by raising the Click event on the relevant control. In this case Windows Forms handles the message by running the supplied delegate.

The result is that only 1 thread is modifying / working with the UI controls at any one point in time (the UI thread).

Note that Invoke makes no guarentees as to the order in which delegates will be run. If its important that two delegates being Invoked from two different threads (or even the same thread) be executed in the correct order then thats a different problem.


Aside: We talk about "the UI thread" because most applications have one thread on which all controls are created, however in reality different controls can be created threads - its the thread that the control was created on which process the message. Obviously in order for those messages to be properly processed there must be a message pump running on that thread.

Community
  • 1
  • 1
Justin
  • 84,773
  • 49
  • 224
  • 367
  • Again, this will not make it predictable. say you have the UI thread and another thread and both try to change the UI. The other threads message can come before or after the UI thread's change, resulting in unpredicatblity. – Yamcha Oct 16 '12 at 13:07
  • @user1316459 Thats not the problem that `Invoke` is attempting to solve - `Invoke` exists because cross-thread UI calls are explicitly disallowed in Windows Forms (see the first link in my answer for a discussion on why). If its important that the UI threads actions come before / after another threads then thats an entirely different problem - `Invoke` makes no guarentees about the order in which messages will be processed. – Justin Oct 16 '12 at 13:16
  • well, first of all, its not completely disallowed. You can just set the Control.checkforillegalcrossthreadcalls to false. but if I don't set it to false, as many encourage, I'd have to use invoke. My point is, it doesn't make anything better. my UI will have the same predictibilty status. – Yamcha Oct 16 '12 at 13:24
  • @user1316459 The "no cross-thread UI calls" rule there is more to protect the internal state of the control than it is to make multi-threading predictable. For example if a `ListView` was to get interrupted between adding an item to its `Items` collection and adding the item to the underlying native control then all sorts of bad stuff could happen. Writing a UI framework without those sorts of restrictions isn't impossible, but it is **very** difficult. – Justin Oct 16 '12 at 13:33
2

Most types aren't actually thread safe, but can be used from multiple threads so long as only one thread uses them at a time.

UI controls aren't quite the same: they have thread affinity - they can only be safely used on the UI thread.

Part of the reason for this is that the UI thread may want to redraw them at any time, so they've got to be available at any time. Combine that with not wanting to delay the UI thread while it waits for a lock, and also combine it with the desire to avoid even uncontested locking if you can help it (and the UI thread would have to take out a lot of locks if it needed to do this for every access) and you get a simplified model where it's easier just to say that all access must be on the UI thread. I'm sure it would be possible to design a UI framework without thread affinity, but getting it to perform and behave predictably would be tricky.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

Invoke is used to make sure you are calling the UI on the correct thread. but this is needed for every .net object. The UI is made to work on a single thread(this is true with WPF and Winforms). Two different threads can access the same object as long as its not at the same time. If it this happens it creates a race case and could end in dead lock

Micah Armantrout
  • 6,781
  • 4
  • 40
  • 66
  • but that really does depend on your code. you can have a race case with an object. On the other hand, you can have multiple threads changing the UI, but still have determínistic behaviour by creating for example Control locks. for example, if a button1 is clicked, then thread 2 can add button2. if button2 is clicked then thread 3 may change the GUI and so on. – Yamcha Oct 16 '12 at 12:54
  • Nope different threads changing the UI will cause an exception – Micah Armantrout Oct 16 '12 at 12:55