I see a lot of threads on google/here on UPDATING a UI element from another thread.
What if I want to just get the value of a checkbox?
Am I able to do this without having to do anything special?
1) Have each thread set a "DataUpdated" flag when new data is available, and have the UI periodically check for new data. 2) Create each thread with a callback to a UI Update(...) method to be called when new data becomes available.
Multiple Windows, Multiple ThreadsSome WPF applications require multiple top-level windows. It is perfectly acceptable for one Thread/Dispatcher combination to manage multiple windows, but sometimes several threads do a better job.
Typically your WPF projects have a single Dispatcher object (and therefore a single UI thread) that all user interface work is channeled through.
Edit: It seems I have to take back what I wrote before. Tried the following:
Added a textbox called myTextBox
and tried to retrieve the value of the Text
property:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
string value = myTextBox.Text;
Thread.Sleep(2000);
});
t.Start();
And it seems that the app (WPF) crashes after 2 seconds. Using the dispatcher works:
Thread t = new Thread(
o =>
{
Thread.Sleep(2000);
myTextBox.Dispatcher.BeginInvoke(
(Action)(() => { string value = myTextBox.Text; }));
Thread.Sleep(2000);
});
t.Start();
Thus, you still need to go through the dispatcher thread when reading values from GUI components, at least in WPF.
Second edit: This gets better. Apparently repeating the experiment for classic WinForms reveals that it works to read the Text
property without using Invoke/BeginInvoke
. Interestingly enough, it seems that also setting the property works fine (without invoke), although I'll wager it's not thread safe and the app doesn't complain for some reason.
Bottom line: It's a good idea in any case to use the dispatcher when interacting with GUI components from other threads, as it ensures the reads/writes are serialized to a single thread and so you have no thread-safety issues.
Can you access UI elements from another thread? (get not set)?
No.
Here is the deal. UI elements have very strict thread affinity requirements. This means you can only access the element from the thread hosting it. This includes all kinds of accesses including simple reads.1
It may work fine for simple property getters, but its perceived safeness would be an accidental result of the way that particular control was implemented. Since Control
instances have thread affinity they could potentially use thread local storage techniques to save some of their state which, of course, would not be compatible with different thread. Or what if the value you are trying to read is in a half-baked state? There would be no way to synchronize access to that read since the write may be occurring inside code you have no control over. And still this is ignoring subtle memory barrier problems that may arise.
Again, if it appears to work then chalk it up as an accident. Accessing UI elements from a thread than the one hosting them is a recipe for disaster. Things may fail unpredictably and spectacularly.
1There are very few exceptions to this rule. Using the ISynchronizeInvoke
methods is one such exception.
You could but strictly it wouldn't be thread safe. For instance if the property Get code would consist of multiple operations, the UI thread could act in the mean time, halfway during the Get operation, causing unexpected results.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With