I have a window form application, and it has multiple threads running that would invoke on the Main UI thread to update the UI. Occasionally on development machine, the app
Please check the code in this answer that can help you to find the exact event handlers that causes your Windows Form application to freeze due threading problem with SystemEvents class.
Disabling the visual styles will also fix the issue (if you do not need them)
//Comment this line if you do not want visual styles and do not want to mess with SystemEvents.
//Application.EnableVisualStyles();
Yes, this is a fairly infamous threading problem caused by the SystemEvents class. I never got a solid diagnostic for it but the 90% odds are that this is triggered by an initialization problem in your app.
The root problem is that SystemEvents gets initialized on-demand by the first form in your app that has controls that are interested in the events it generates. If that first form is not created in the main thread then SystemEvents is helpless to guess at which thread is the UI thread in your program. Eventually, when a notification is received (like UserPreferenceChanging), it tries to fire the event on that thread, but it isn't around anymore. The fallback code in the SynchronizationContext class raises the event on a threadpool thread instead. That inevitably invokes Threading Hell by running UI code on a thread that didn't create the window. Lots of things can go wrong when that happens. Deadlock is a particularly common outcome when restoring the desktop after the workstation was locked.
Not the only possible way this can go wrong, it is inevitable if you create any form on another thread. Now SystemEvents cannot possibly raise the event on the correct thread of course, somebody is going to lose. A blog post that demonstrates a debugging technique is here. Yes, ugly. Ideally a control knows to deal with this and marshal the notification itself. But that was forgotten knowledge at .NET 2.0, DataGridView, NumericUpDown, DomainUpDown, ToolStrip+MenuStrip and the ToolStripItem derived classes don't do this. I should note that RichTextBox and ProgressBar are suspicious, the rest are okay.
Review the startup sequence of your app. Creating your own splash screen is a good lead, do favor using the built-in support that the WindowsFormsApplicationBase class provides. If you do it yourself then keep it very simple, just a bitmap. And as noted, any place where you might create your own form on a worker thread is a recipe for trouble. Always do it the other way around, run the expensive code on a worker and keep the UI on the main thread.
I experienced this exact same issue about a year ago (application hang after some time without user interaction, with OnUserPreferenceChanging()
in the call stack).
The most likely cause is that you're using InvokeRequired
/Invoke()
on a control and not on the main form. This sometimes produces the wrong result if the control's handle hasn't been created yet.
The solution is to always call InvokeRequired
/Invoke()
on the Main Window (which you can cast as an ISynchronizeInvoke
if you don't want to introduce a dependency to your form class).
You can find an excellent, very detailed description of the cause and solution here.
I have been suffering this exact same problem and it was always due to the Microsoft.Win32.SystemEvents.DisplaySettingsChanged event that happens way more frequently under Windows 8.1 and also also when my application was running and someone connected with VNC or RDP. It was also very clear when using Windows x.x with Fusion (VMWare) over Mac that changes the desktop settings from time to time.
After trying lot of things I finally got it resolving by listening these events in my MainApp (the one that create all dialogs and also perform all Invoke)
Declare:
Microsoft.Win32.SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
Microsoft.Win32.SystemEvents.DisplaySettingsChanging += SystemEvents_DisplaySettingsChanging;
Microsoft.Win32.SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
Implement:
static void SystemEvents_UserPreferenceChanged(object sender, Microsoft.Win32.UserPreferenceChangedEventArgs e)
{
//Do nothing
}
static void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
//Do nothing
}
static void SystemEvents_DisplaySettingsChanging(object sender, EventArgs e)
{
//Do nothing
}
The capture of these events do nothing but this seems to be voiding the deadlock I was having when these events were coming from windows and any other part of my code was waiting for MainApp to attend an Invoke.
Hope this helps.