Can you access UI elements from another thread? (get not set)
Solution 1:
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.
Solution 2:
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.
Solution 3:
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.