Reputation: 2632
Let's assume that the code running in the thread that instantiated the form/control/element (usually the main thread) does not modify/access that element at the same time, is it possible to:
get the Text property of a TextBox.
enumerate a ListView.
subscribe to a Form's Closing event. (Knowing that the hook will be called from the thread that instantiated that form)
I have tried all 3 and the program doesn't seem to complain about it. I had always thought that you had to invoke any call that wants to even remotely touch anything UI related (read or write).
I understand very clearly why I need to use the IsInvokeRequired/Invoke pattern when modifying an element, but I cannot see why accessing properties/events would cause any problems.
Upvotes: 3
Views: 530
Reputation: 48959
This is not safe. The UI thread could (and probably will) change the state of the control while you are reading it from another thread. Your reads might catch the control in a half-baked state. It may appear to be working now, but sooner or later it will fail...probably unpredictably and spectacularly.
No, you probably do not need to use the Invoke pattern. To be quite frank...that pattern is usually the worst option. It is usually better to have your worker thread do the heavy lifting and then send new data or progress information to the UI thread via a queue and let the UI thread pick this up via a timer. This has several advantages.
Invoke
and BeginInvoke
operations.Invoke
to return.BeginInvoke
.You will need to enumerate the ListView
and build up a separate data structure that can then be accessed by the worker thread safely. If the ListView
contains a lot of items consider maintaining a separate collection in tandem with the control. That way you spread out the penalty of coping the data over a bigger period of time in which it probably will not be noticed as much. Afterall, we do not want the copy operation to freeze the UI thread otherwise a user will notice. A ConcurrentBag
or the like might be a good choice since it can be safely modified by the UI thread while the worker thread is reading it.
Upvotes: 2
Reputation: 82136
It's definitely possible, however, it could lead to unexpected behaviour. Also, other thread-related bugs also need to be taken into consideration e.g. race conditions/deadlocks see Managed Threading Best Practises.
I would always stick to accessing the UI on the UI thread to be on the safe side.
Upvotes: 5
Reputation: 203825
And what are you doing to ensure that the UI thread isn't modifying the control while you're reading from it? The whole reason for marshaling to the UI thread is so that you don't need to worry about that case. Enumerating the listbox in particular is going to be the easiest to break as it will take the longest time (this creating the largest window for a race condition). You should be marshaling to the UI thread for all 3 of those things.
Upvotes: 3