In my C# Windows Forms application there are two threads:
Main Thread (Program.cs)
WorkerClass Thread (STA-Apartment).
When there is long running Task, it freeze/stuck the entire process and No exception or notification fired..it hangs application.
Internally applications doing processing of records only (selection from SQL tables & inserting in Access DB tables)
UI updates will be done using event Action feature.
Find attached snap for stuck process parallel tasks. Seems like threads internally wait for each other and get process blocked. Code related to the SystemEvents.UserPreferenceChanged event is on one of the stacks.
Why does this happen and how can I resolve it?
It deadlocks on a SystemEvents.UserPreferenceChanged event. This is the standard way an app with windows on more than one thread deadlocks. Best way to invoke the deadlock is to press the Windows+L key. You can see this deadlock analyzed in depth in this blog post.
The SystemEvents class is the troublemaker here, it makes an attempt to raise it events on the UI thread of a program. Which is very important, UI isn't thread-safe. Trouble is, you've got two threads that created UI. SystemEvents is incapable of guessing which one is right, it only has 50% odds at it so is doomed to get it wrong. If it initially guessed wrong at which thread in your program is the UI thread, and that thread exited, then it will be 100% wrong.
This makes creating UI on a worker thread exceedingly hazardous of course. It is technically possible, you'll however have to avoid using several controls from the toolbox. They don't handle the UserPreferenceChanged event well when it is raised on the wrong thread. The ones that definitely cause deadlock are DataGridView, NumericUpDown, DomainUpDown, ToolStrip+MenuStrip and the ToolStripItem derived classes. The ones that are iffy (can't analyze the code deep enough) are RichTextBox and ProgressBar. Looks like I ought to put ProgressBar in the first set, judging from your callstacks.
The true cure is to not create UI on a worker thread. It is never necessary, the UI thread of your program is already capable of handling any number of windows.
Related
I think my problem is similar to:
.NET 4.0 and the dreaded OnUserPreferenceChanged Hang
I have also looked through:
http://ikriv.com/en/prog/info/dotnet/MysteriousHang.html#BeginInvokeDance
I have removed our splash screen.
I also tried adding the suggested code: Microsoft.Win32.SystemEvents.UserPreferenceChanged += delegate { }; to our main() method.
I'm looking for some ideas and information on how to troubleshoot.
For our main() method we start a windowmanager class which is a form using Application.Run
It is just an icon in the task tray ( we don't show a window).
Whenever we launch an object we have a background thread which creates a form and then does Application.Run( form )
At the time of Application.Run( form ) form.IsHandleCreated = false.
I use the freezer application from the MysteriousHang website. (I modified it to keep sending the change notification in a loop ).
How should I be handling creating and running the new form? Does it matter that the form is created on the background thread even if its handle isn't created yet?
I'm also confused about the terminology "UI thread".
A UI thread is a thread that pumps a message loop. And operates in a mode that's compatible with user interface objects, it needs to be an STA, a Single Threaded Apartment. That's a COM implementation detail that matters a great deal to common UI operations that are not thread-safe and require an STA, like Drag+Drop, the Clipboard, shell dialogs like OpenFileDialog and ActiveX components.
It is the CLR's job to call CoInitializeEx() and select the apartment type. It does so guided by the [STAThread] attribute on the Main() entrypoint in your program. Present in projects that create UI objects like a Winforms or WPF app. But not a console mode app or service. For a worker thread, in other words a thread that was created by your code instead of Windows, the apartment type is selected by what you passed to Thread.SetApartmentState() method. The default is MTA, the wrong flavor. A threadpool thread is always MTA, that cannot be changed.
The SystemEvents class has the unenviable task of figuring out which thread is the UI thread in your program. Important so it can raise events on the correct thread. It does so by using a heuristic, the first thread that subscribes an event and is an STA thread is considered suitable.
Things go wrong when that guess wasn't accurate. Or certainly in your case where you try to create multiple threads that create UI objects, the guess can only ever be correct for one of them. You probably also forgot to call Thread.SetApartmentState() so it won't be correct for any of them. WPF more strongly asserts this and will generate an exception when the thread isn't STA.
The UserPreferenceChanged event is a trouble-maker, it is subscribed by some of the controls you find on the toolbox. They use it to know that the active visual style theme was changed so they'll repaint themselves, using the new theme colors. A significant flaw in the event handlers in some of these controls is that they assume that the event is raised on the correct thread, the same thread that created the control object.
This will not be the case in your program. The outcome tends to be unpleasant, subtle painting problems are a minor flaw, deadlock is certainly possible. For some reason, locking the work station with Windows+L and unlocking it is particularly prone to causing deadlock. The UserPreferenceChanged event is raised in that case because of the desktop switch from the secure desktop the user's desktop.
The controls that listen to the UserPreferenceChanged event and do not use safe threading practices (using Control.BeginInvoke) are DataGridView, NumericUpDown, DomainUpDown, ToolStrip+MenuStrip and the ToolStripItem derived classes, possibly RichTextBox and ProgressBar (unclear).
The message ought to be clear, you are using unsafe threading practices and they can byte. There in general is never any point to creating UI on a worker thread, the main thread of a Winforms or WPF program is already quite capable of supporting multiple windows. Short from avoiding the dangerous controls, this is what you should strive for to get rid of the problem.
Is there anyway to run a large number of UI updates without effecting the main thread in a C# winforms application?
I would like to avoid a long delay when a user clicks a specific event (which in my case is many close form calls to dispose of memory)
I know i can use BackgroundWorker to perform lengthy operations in the "do work" event, but the problem is that you cant change any UI in this event (it will cause a cross thread exception) - so i cant put my large number of close form calls here.
And I cant put the close form calls in the "worker completed" event because this is run on the main thread, and will eventually lockup the main thread causing a bad user experience.
I have thought about spawning a thread to handle closes only when the appication session is idle, but not sure if this is going to be a bit messy.
You should use ProgressChanged event of BackgroundWorker to update UI. To enable this feature set WorkerReportsProgress property of your BackgroundWorker instance to true. Then you can update UI many times by sending data from DoWork event handler:
backgroundWorker.ReportProgress(percentage, yourCustomData);
It is recommended to Make Thread-Safe Calls to Windows Forms Controls. Here is the reason:
Access to Windows Forms controls is not inherently thread safe. If you
have two or more threads manipulating the state of a control, it is
possible to force the control into an inconsistent state. Other
thread-related bugs are possible as well, including race conditions
and deadlocks. It is important to ensure that access to your controls
is done in a thread-safe way.
The .NET Framework helps you detect when you are accessing your
controls in a manner that is not thread safe. When you are running
your application in the debugger, and a thread other than the one
which created a control attempts to call that control, the debugger
raises an InvalidOperationException with the message, "Control control
name accessed from a thread other than the thread it was created on."
This exception occurs reliably during debugging and, under some
circumstances, at run time. You are strongly advised to fix this
problem when you see it.
You can disable that exception:
Form.CheckForIllegalCrossThreadCalls = false;
But controls could (and sometime will) stop working.
I know how to pass data from a worker thread to the main thread via Invoke/BeginInvoke.
I can also pull from a thread safe collection with a timer from the main thread.
I prefer using tasks (Task.Factory.StartNewTask()) and using Backgroundworker with them seams a bit clumsy.
Sometimes the gui is a bit laggy which is due to (Begin)Invoke I assume.
Pulling with a timer also doesn't feel like the right way.
Creating a new Backgroundworker for each new task seams also strange.
Are there any other possibilities?
In .NET, memory is shared within an AppDomain, which means all threads can access all data. So, what you're actually doing is controlling access to particular bits of data from particular threads so they don't interfere with each other.
Invoke and BeginInvoke allow you to run code on the UI thread, which is useful because UI controls can only be accessed from the UI thread. BackgroundWorker is another solution, as is SynchronizationContext.
However, they all work by sending known windows messages to the UI message loop. If you call Invoke too often, you send too many messages and the UI thread is swamped which makes the UI "a bit laggy".
If this happens, you must slow down the rate that messages are sent. There are a couple of ways to do this:
1) Call Invoke less frequently: this means waiting for bigger "chunks" of state changes in your background thread before it calls Invoke to update the UI.
2) Use a UI Timer: there is no point in trying to update the UI faster than the human eye can detect. A UI Timer also sends windows messages to the UI message loop, but at a known rate. The Tick handler can then pull the necessary data from shared memory to update the UI.
Both approaches have their strengths and weaknesses. The choice really depends on how easy it is to group state changes in the background thread into bigger chunks, while making sure the UI doesn't miss any state changes.
I am working on a network application with threading. I have an event handler which results in a form showing on the screen. The problem is that the thread that makes this call blocks right after, so the form that shows blocks as well.
I have hacked this problem by making that function change something in the form it's currently in, and then used invoke required to force the new form onto that thread. This is a terrible hack, what is the right way to make the new form.Show() method go through its own thread.
Note that I have tried just making a worker thread that runs only form.show() but the form disappears right after the call.
Thank you,
PM
You don't want UI elements being created in their own threads. The primary thread that launched your application should be the UI thread. Create and show all elements on this thread. All your heavy, long-time or blocking work should be done on their own threads.
You can use BackgroundWorker to execute a single additional task without blocking your UI and get automatic synchronization when you need to make updates to the main (UI) thread such as to update progress bars or show a final result.
If you need multiple threads doing long-running work, use the ThreadPool. You will have to do your own cross-thread synchronization if you need to update UI elements. There are a ton of answers on how to do that already if that's the route you go.
If you have multiple threads that are being blocked while waiting for something to happen, you should use threads yourself. This will keep the ThreadPool from being starved of threads because they are all blocking. (I believe this has been changed in .NET 4 so if you're targeting that version you can probably easily continue using the ThreadPool in this situation.)
Have you tried placing the blocking call in a BackgroundWorker (separate thread)? When that blocking call is done, your background-worker thread completes (which is handled by your main UI thread). Then in that completed handler you can show your form/message or whatever...
If you haven't tried that then give it a shot. Note that i have not tested this since i dont know exactly what you're doing.
Cheers.
I have a WinForms app written in C# with .NET 3.5. It runs a lengthy batch process. I want the app to update status of what the batch process is doing. What is the best way to update the UI?
The BackgroundWorker sounds like the object you want.
The quick and dirty way is using Application.DoEvents() But this can cause problems with the order events are handled. So it's not recommended
The problem is probably not that you have to yield to the ui thread but that you do the processing on the ui thread blocking it from handling messages. You can use the backgroundworker component to do the batch processing on a different thread without blocking the UI thread.
Run the lengthy process on a background thread. The background worker class is an easy way of doing this - it provides simple support for sending progress updates and completion events for which the event handlers are called on the correct thread for you. This keeps the code clean and concise.
To display the updates, progress bars or status bar text are two of the most common approaches.
The key thing to remember is if you are doing things on a background thread, you must switch to the UI thread in order to update windows controls etc.
To beef out what people are saying about DoEvents, here's a description of what can happen.
Say you have some form with data on it and your long running event is saving it to the database or generating a report based on it. You start saving or generating the report, and then periodically you call DoEvents so that the screen keeps painting.
Unfortunately the screen isn't just painting, it will also react to user actions. This is because DoEvents stops what you're doing now to process all the windows messages waiting to be processed by your Winforms app. These messages include requests to redraw, as well as any user typing, clicking, etc.
So for example, while you're saving the data, the user can do things like making the app show a modal dialog box that's completely unrelated to the long running task (eg Help->About). Now you're reacting to new user actions inside the already running long running task. DoEvents will return when all the events that were waiting when you called it are finished, and then your long running task will continue.
What if the user doesn't close the modal dialog? Your long running task waits forever until this dialog is closed. If you're committing to a database and holding a transaction, now you're holding a transaction open while the user is having a coffee. Either your transaction times out and you lose your persistence work, or the transaction doesn't time out and you potentially deadlock other users of the DB.
What's happening here is that Application.DoEvents makes your code reentrant. See the wikipedia definition here. Note some points from the top of the article, that for code to be reentrant, it:
Must hold no static (or global) non-constant data.
Must work only on the data provided to it by the caller.
Must not rely on locks to singleton resources.
Must not call non-reentrant computer programs or routines.
It's very unlikely that long running code in a WinForms app is working only on data passed to the method by the caller, doesn't hold static data, holds no locks, and calls only other reentrant methods.
As many people here are saying, DoEvents can lead to some very weird scenarios in code. The bugs it can lead to can be very hard to diagnose, and your user is not likely to tell you "Oh, this might have happened because I clicked this unrelated button while I was waiting for it to save".
Use Backgroundworker, and if you are also trying to update the GUI thread by handling the ProgressChanged event(like, for a ProgressBar), be sure to also set WorkerReportsProgress=true, or the thread that is reporting progress will die the first time it tries to call ReportProgress...
an exception is thrown, but you might not see it unless you have 'when thrown' enabled, and the output will just show that the thread exited.
Use the backgroundworker component to run your batch processing in a seperate thread, this will then not impact on the UI thread.
I want to restate what my previous commenters noted: please avoid DoEvents() whenever possible, as this is almost always a form of "hack" and causes maintenance nightmares.
If you go the BackgroundWorker road (which I suggest), you'll have to deal with cross-threading calls to the UI if you want to call any methods or properties of Controls, as these are thread-affine and must be called only from the thread they were created on. Use Control.Invoke() and/or Control.BeginInvoke() as appropriate.
If you are running in a background/worker thread, you can call Control.Invoke on one of your UI controls to run a delegate in the UI thread.
Control.Invoke is synchronous (Waits until the delegate returns). If you don't want to wait you use .BeginInvoke() to only queue the command.
The returnvalue of .BeginInvoke() allows you to check if the method completed or to wait until it completed.
Application.DoEvents() or possibly run the batch on a separate thread?
DoEvents() was what I was looking for but I've also voted up the backgroundworker answers because that looks like a good solution that I will investigate some more.