I have several System.Threading.Timers on my form application with callbacks that update the UI...successfully - i.e. without throwing errors.
I had built these earlier, before I knew that UI should not be updated on any thread other than the UI thread.
Now I am confused as to why it does not throw cross-thread exceptions when I am updating UI on these separate threading.timer threads?
I will be changing these callbacks so that the UI updates are invoked on UI thread, but I am curious as to why this works.
Edit: My application is a WinForms Application.
I will be changing these callbacks so that the UI updates are invoked on UI thread, but I am curious as to why this works.
If this is Windows Forms, it works purely by luck. Updating a UI on a background thread doesn't consistently work, but occasionally will not throw. In particular, if CheckForIllegalCrossThreadCalls is false, it will sometimes "work", and never throw - though the behavior is often wrong. Some controls do not always check every property, so some items "work" even though they're not always working correctly, as this typically introduces bugs that can be difficult to diagnose and correct later.
On a side note: If this were WPF, you could change the value of a item bound to your UI, effectively updating your UI, on a background thread. The WPF binding system will automatically marshal this to the UI thread for you. It does not work to change part of a collection, however.
I've also experienced this with WinForms. See here: Can you access UI elements from another thread? (get not set) It works by "magic" (read "in a random manner") in my opinion, and should not be taken as an invitation to do it in practice. It's by no means a thread-safe way of updating the GUI. Sometimes the program just does not complain.
In .NET 1.0 and 1.1, no cross-thread checking is performed, so you will never get an InvalidOperationException (although MSDN acknowledges that performing cross-thread updates “often leads to unpredictable results”, which may including application crashes).
In .NET 2.0 and later, cross-thread checking is performed depending on the value of the Control.CheckForIllegalCrossThreadCalls static property. Its default value is initialized from the Debugger.IsAttached static property (which indicates whether a debugger is attached to the process), meaning that cross-thread checking is not performed when the application is run on its own (without Visual Studio or any other debuggers attached to it).
This setting may, of course, be overridden by user code, including referenced libraries.
I believe this has to do with what type of Timer you are creating. There are two types:
System.Timers.Timer;
System.Windows.Forms.Timer
There is a distinct difference between these two, the System.Timers.Timer will throw exceptions if you update the UI, and the System.Windows.Forms.Timer will not. If you have a using statement :"Using System.Windows.Forms" and simply have a "Timer" this will be the Windows.Forms.Timer which is distinctly different from the System.Timers.Timer.
Under the hood (I believe) System.Windows.Forms.Timer is trapping a WM_TIMER message, so you are on the thread that is updating the GUI.
Related
I'm coming from WPF and I am new to WinForms. While investigating a cross-threading situation, a cross-thread exception that I expected did not occur.
Here is a basic summary of my situation. There is one Label control named label1 and one Button named button1. The click event handler for button1 essentially looks like this:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(()=>
{
label1.Text = "Some-Other-New-Text";
});
}
This is not throwing a cross-thread exception as I expect it to. Is this because WinForms applications do not have cross-threading problems? Note that I have investigated this in Visual Studio 2013 as well as in Visual Studio 2010.
Windows forms work on top of the Windows messaging infrastructure. That means that a lot of the operations you perform on the controls in question are actually delegated to Windows to support proper native behaviour of all the controls.
Label doesn't change the default implementation, and it doesn't cache the text in managed code by default. This means that it uses the SetWindowText native method to set the current label text (and correspondingly, GetWindowText to read it), which posts a WM_SETTEXT to the message loop. The real update happens on the thread that handles the message loop, also known as the UI thread. Unless you go out of your way to prohibit this kind of call (Control.checkForIllegalCrossThreadCall in current reference source), it will work. By default, this is set depending on whether a debugger is attached - so your code may crash while debugging, but will work outside of a debugger, since SetWindowText happens to be thread-safe. There's other parts of the Text property that may or may not be thread-safe, but if you're lucky, everything works just fine.
You can set Control.CheckForIllegalCrossThreadCall to true explicitly, and I'd recommend you to do so. Accessing any resource from multiple threads is prone to hard to debug issues, and marshalling whatever work needs to be done on the UI to the UI thread is... kind of the job of the UI thread anyway.
Manipulating the UI exclusively from the UI thread gives you quite important benefits:
Predictability and realiability - things will tend to happen in certain reliable orders. If I have a hundred threads setting the Textof two different controls, delegating the UI update to the UI thread will ensure that the two controls always have consistent values, while updating directly from the background threads will tend to interleave the updates "randomly". In a real application, this can cause confusion as well as hard to find bugs. Note that this isn't absolute - any await/Application.DoEvents may or may not disrupt this. But even in that case, you have well defined synchronization points, rather than preëmptive multi-tasking.
Multi-threading is hard. Most things you work with aren't thread-safe, and even allegedly thread-safe operations may have multi-threading bugs or simply complicated behaviour when running in a MT scenario. Even a simple thing like updating two booleans in a sequence becomes dangerous, and may introduce hard to debug bugs. Your best bet is to keep as many things thread-affine as you can. You'll usually find you can confine all interfaces between the threads to a tiny portion of your code, which makes them much easier to test and debug.
It's really cheap when you've already separated "work" from "UI" anyway. And that's a pretty handy design practice on its own.
As a side-note, you usually want to await tasks that you spin off, or handle exceptions explicitly. If you enable Control.CheckForIllegalCrossThreadCall, the label will no longer update, but it will not show an exception either - by default, threadpool threads ignore unhandled exceptions nowadays (since .NET 4.5.2 IIRC). The await will marshall any exceptions (and return values) back to the UI thread.
In my situation, I expected a cross-thread exception (in the debugger†) in my WinForms application when accessing a ToolStripStatusLabel from a thread other than the UI thread.
I discovered that the reason that the cross-thread exception does not occur is because ToolStripStatusLabel does not derive from System.Windows.Forms.Control and therefore does not have a CheckForIllegalCrossThreadCalls property.
(I was able to narrow this down by first proving that attempting to access a TextBox in a non-UI thread did raise the cross-thread exception.)
† See this answer as to why WinForms cross-thread exceptions typically happen only when you are debugging.
I know that if I am modifying a control from a different thread, I should take care because WinForms and WPF don't allow modifying control's state from other threads.
Why is this restriction in place?
If I can write thread-safe code, I should be able to modify control state safely. Then why is this restriction present?
Several GUI frameworks have this limitation. According to the book Java Concurrency in Practice the reason for this is to avoid complex locking. The problem is that GUI controls may have to react to both events from the UI, data binding and so forth, which leads to locking from several different sources and thus a risk of deadlocks. To avoid this .NET WinForms (and other UIs) restricts access to components to a single thread and thus avoids locking.
In the case of windows, when a control is created UI updates are performed via messages from a message pump. The programmer does not have direct control of the thread the pump is running on, therefore the arrival of a message for a control could possibly result in the changing of the state of the control. If another thread (that the programmer was in direct control of) were allowed to change the state of the control then some sort of synchronization logic would have to be put in place to prevent corruption of the control state. The controls in .Net are not thread safe; this is, I suspect by design. Putting synchronization logic in all controls would be expensive in terms of designing, developing, testing and supporting the code that provides this feature. The programmer could of course provide thread safety to the control for his own code, but not for the code that is in .Net that is running concurrently with his code. One solution to this issue is to restrict these types of actions to one thread and one thread only, which makes the control code in .Net simpler to maintain.
.NET reserves the right to access your control in the thread where you created it at any time. Therefore accesses that come from another thread can never be thread safe.
You might be able to make your own code thread-safe, but there is no way for you to inject the necessary synchronization primitives into the builtin WinForm and WPF code that match up with the ones in your code. Remember, there are a lot of messages getting passed around behind the scenes that eventually cause the UI thread to access the control without you really ever realizing it.
Another interesting aspect of a controls thread affinity is that it could (though I suspect they never would) use the Thread Local Storage pattern. Obviously if you accessed a control on a thread other than the one it was created on it would not be able to access the correct TLS data no matter how carefully you structured the code to guard against all of the normal problems of multithreaded code.
Windows supports many operations which, especially used in combination, are inherently not thread-safe. What should happen, for example, if while one thread is trying to insert some text into a text field starting with the 50th character, while another thread tries to delete the first 40 characters from that field? It would be possible for Windows to use locks to ensure that the second operation couldn't be begun until the first one completed, but using locks would add overhead to every operation, and would also raise the possibility of deadlock if actions on one entity require manipulation of another. Requiring that actions involving a particular window must happen on a particular thread is a more stringent requirement than would be necessary to prevent unsafe combinations of operations from being performed simultaneously, but it's relatively easy to analyze. Using controls from multiple threads and avoiding clashes via some other means would generally be more difficult.
Actually, as far as I know, that WAS the plan from the beginning! Every control could be accessed from any thread! And just because thread locking was needed when another thread required access to the control --and because locking is expensive-- a new threading model was crafted called "thread rental". In that model, related controls would be aggregated into "contexts" using only one thread, thus reducing the amount of locking needed.
Pretty cool, huh?
Unfortunately, that attempt was too bold to succeed (and a bit more complex because locking was still required), so the good old Windows Forms threading model --with the single UI thread and with the creating thread to claim ownership of the control-- is used once again in wPF to make our lives ...easier?
I'm building a WPF application. I'm doing some async communication with the server side, and I use event aggregation with Prism on the client. Both these things results in new threads to be spawned which are not the UI thread. If I attempt to do "WPF operations" on these callback and event handler threads the world will fall apart, which it now has started doing.
First I met problems trying to create some WPF objects in the callback from server. I was told that the thread needed to run in STA mode. Now I'm trying to update some UI data in a Prism event handler, and I'm told that:
The caller cannot access this thread because a different thread owns it.
So; what's the key to getting things right in WPF? I've read up on the WPF Dispatcher in this MSDN post. I'm starting to get it, but I'm no wizard yet.
Is the key to always use Dispatcher.Invoke when I need to run something which I'm not sure will be called on the UI thread?
Does it matter if it actually was called on the UI thread, and I do Dispatcher.Invoke anyway?
Dispatcher.Invoke = synchronously. Dispathcher.BeginInvoke = async?
Will Dispatcher.Invoke request the UI thread, and then stop to wait for it? Is it bad practice and risk of less responsive programs?
How do I get the dispatcher anyway? Will Dispatcher.CurrentDispatcher always give me the dispatcher representing the UI thread?
Will there exist more than one Dispatcher, or is "Dispatcher" basically the same as the UI thread for the application?
And what's the deal with the BackgroundWorker? When do I use this instead? I assume this is always async?
Will everything that runs on the UI thread (by being Invoked) be run in STA apartment mode? I.e. if I have something that requires to be run in STA mode - will Dispatcher.Invoke be sufficient?
Anyone wanna clearify things for me? Any related recommendations, etc? Thanks!
Going over each of your questions, one by one:
Not quite; you should only invoke onto the UI thread when necessary. See #2.
Yes, it does matter. You should not just automatically Invoke everything. The key is to only invoke onto the UI thread if necessary. To do this, you can use the Dispatcher.CheckAccess method.
That is correct.
Also correct, and yes, you do run the risk of less responsive programs. Most of the time, you are not going to be looking at a severe performance hit (we're talking about milliseconds for a context switch), but you should only Invoke if necessary. That being said, at some points it is unavoidable, so no, I would not say it is bad practice at all. It is just one solution to a problem that you will encounter every now and then.
In every case I have seen, I have made due with Dispatcher.CurrentDispatcher. For complex scenarios, this may not be sufficient, but I (personally) have not seen them.
Not entirely correct, but this line of thinking will not do any harm. Let me put it this way: the Dispatcher can be used to gain access to the UI thread for the application. But it is not in and of itself the UI thread.
BackgroundWorker is generally used when you have a time-consuming operation and want to maintain a responsive UI while running that operation in the background. Normally you do not use BackgroundWorker instead of Invoke, rather, you use BackgroundWorker in conjunction with Invoke. That is, if you need to update some UI object in your BackgroundWorker, you can Invoke onto the UI thread, perform the update, and then return to the original operation.
Yes. The UI thread of a WPF application, by definition, must be running in a single-threaded apartment.
There's a lot to be said about BackgroundWorker, I'm sure many questions are already devoted to it, so I won't go into too much depth. If you're curious, check out the MSDN page for BackgroundWorker class.
I was debugging an application and somewhere in the code, a thread tries to reach a listbox that was created by another thread. On attempt to access the listbox, the application throws a "Cross-thread operation not valid: Control 'listbox' accessed from a thread other than the thread it was created on" exception while debugging. However, when I run this application's output in bin\Debug folder, I do not get an exception dialog and I can see that the listbox is successfully accessed from the non-owner thread, so this makes me think that there is a behavioral difference here, not just a suppressed exception. I can get past this exception in debugging with the following line in form_load event
Control.CheckForIllegalCrossThreadCalls = false;
But what is the reason behind this different behavior?
Yes, this is only checked when a debugger is attached. This was necessary because there was lots of .NET 1.x code that violated this rule. It is not an obvious one.
The bigger problem is that such code got away with it. Either by luck, not thinking too much about the occasional painting problems or by thinking that aborting the app when it deadlocked and restarting it once a day was acceptable. Because the programmer had no real hope of discovering the problem without a diagnostic.
Microsoft cares a lot about backward compat, even if it is buggy compat. The fix is excellent, even though it is sometimes wrong (Show(owner) is checked when it shouldn't). And sometimes overlooks to check when it is code in the framework that violates the rule. Which happens when the thread dependency is indirect. Most common cases of that are updating the data source of a data-bound control in a worker thread (unbind first!) and using a control that listens for the SystemEvents.UserPreferenceChanged event (don't create UI on a second thread!)
For reference, the relevant code is present in the static constructor of the Control class:
static Control()
{
//...
checkForIllegalCrossThreadCalls = Debugger.IsAttached;
//...
}
We're creating a few threads in a Windows.Forms solution.
We've also got a BrowserControl (yup, it's OAUTH) and of course I'm finding issues with debugging -
Cross-thread operation not valid: Control 'xxForm' accessed from a
thread other than the thread it was created on
And yet I am calling 'correctly'
xxForm.Show()
by ensuring it's wrapped in an invoke call
.Invoke(new MethodInvoker())
and still I get the thread issue. I can do everything else (Focus, BringToFront) it's the Show that errors.
Moreover, the GUI never gets the browser response and shows. In the VS debugger I get the above threading erropr (apartment state of background thread == MTA). When run as an EXE the same code has a threading aparement of STA and the GUI will never show when debugging, but if I run the EXE directly, there's no threading issue, the browser control just never responds to input.
Spo the questions are:
Why the different behjaviour in VS / EXE?
How do I debug in VS?
Does the BrowserControl play ok with multiple threads?
Update
YES I KNOW there's no code - it's too long. I'll see what I can do.
Also please read the question before posting an answer. I am invoking the background thread on the UI thread. That's not the issue. This has NO EFFECT on the result. I'll down vote answers that recommend that.
Also some hope - I've searched for many hours. It's linked the the message pump. Unless the message pump is running the DocumentCompleted event isn't received.
Update 2
Best I manage is pseudo code:
Program:
startWorkQueue
LoadForm (don't show)
Thread1:
addToQueue
Thread2:
readFromQueue
ShowForm (on occasion)
Now the ShowForm method is on a Windows.Form control.
Within this any call is made via an Invoke, so that despite the 2nd thread making the call the ShowForm, the actual .Show() etc etc calls are on the UI thread.
So what am I missing? I just don't understand why there's a cross thread exception....
Ok I've found out what was going on and I'll post here for reference.
I hope it helps someone in the future.
We had some different constraint to the vanilla Forms applications - our Forms were created on the Main thread but had Show() called on a different thread. We also don't have a starting UI - we sit in the background and sometimes react to events with UI prompts.
As such a number of issues hit us. Rather than list them all I'll detail our takeaways:
Application.Run
If decide NOT to Show a Form at the start of your application… then you'll need to consider threads carefully (see Form.Show notes)
Form.Show
This does all resource allocation etc, NOT the Load/ctor
Performs handle creation / resource allocation
Handle creation
Hwnd
If we attempt to access certain Form properties before it has Show(n) then you'll need to create a handle manually (or an Exception is created)
• As easy as if (!IsHandleCreated) { CreateHandle(); }
HOWEVER
This create the control/form
Therefore the control/form is created on the Thread that calls the Handle create
This must be the same UI thread (STA) as the Main function
• Otherwise much weirdness occurs
SO
You aren't restricted by what to do with Application.Run
You can access properties in .Show (but you may need to create a handle first)
You can call Show from a different thread, but ensure the handle is ONLY created on the main thread
I hope it helps, I can provide more details on our specific problems if need be.
Various aids that helped included displaying ManagedThread AND ProcessId in the log and scouring MSDN.
Since the code has not been pasted, I would like to remind you that in WinForms, the UI elements should be accessed only on the UI thread. Any other thread apart from UI thread should not be updating the UI elements directly.