Как бороться с этим зависанием C #, используя SystemEvents.OnUserPreferenceChanged - PullRequest
2 голосов
/ 29 ноября 2011

У моего приложения WinForm возникла проблема с зависанием. Случается, что клиенты иногда оставляют приложение работающим на ночь, а когда они возвращаются утром, приложение обычно находится в состоянии зависания. Это то, что я вижу в файле дампа в главном потоке. Чего я не понимаю, так это того, что может вызвать событие SystemEvents.OnUserPreferenceChanged, хотя я не думаю, что делаю что-либо, что вызывает это событие.

0024e480 770496f4 System.Threading.WaitHandle.WaitOneNative(Microsoft.Win32.SafeHandles.SafeWaitHandle, UInt32, Boolean, Boolean)  
0024e52c 702c68af System.Threading.WaitHandle.WaitOne(Int64, Boolean)  
0024e548 702c6865 System.Threading.WaitHandle.WaitOne(Int32, Boolean)  
0024e55c 6e891a6f System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle)  
0024e570 6ebcd6eb System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean)  
0024e610 6e8933cc System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[])  
0024e644 6eac0c83 System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback, System.Object)  
0024e65c 6fe1eed2 Microsoft.Win32.SystemEvents+SystemEventInvokeInfo.Invoke(Boolean, System.Object[])  
0024e690 6fe1d07f Microsoft.Win32.SystemEvents.RaiseEvent(Boolean, System.Object, System.Object[])  
0024e6dc 6fe1e38f Microsoft.Win32.SystemEvents.OnUserPreferenceChanged(Int32, IntPtr, IntPtr)  
0024e6fc 6fa64c29 Microsoft.Win32.SystemEvents.WindowProc(IntPtr, Int32, IntPtr, IntPtr)  
0024e700 000a1104 [InlinedCallFrame: 0024e700]   
0024e8d8 6e378d5e System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)  
0024e974 6e3789c7 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)  
0024e9c8 6e378811 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)  
0024e9f8 6e88de47 System.Windows.Forms.Application.RunDialog(System.Windows.Forms.Form)  
0024ea0c 6e8c25cb System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window)  
0024ea98 6e8c27e3 System.Windows.Forms.Form.ShowDialog()  
0024ea9c 56c26e76 MyNameSpace.MyForm.MyMethod2(Object, Boolean, Boolean, System.Guid, Boolean)  
0024eba0 56c26c47 MyNameSpace.MyForm.MyMethod1(System.Guid, System.Guid, System.Guid, Boolean)  
0024ecf8 56c91f4c MyNameSpace.MyForm.MyButton_Click(System.Object, System.EventArgs)  
0024ee88 6e334180 System.Windows.Forms.Control.OnClick(System.EventArgs)  

1 Ответ

4 голосов
/ 29 ноября 2011

Элементы управления подписываются на это событие, так что они будут перерисовывать себя, когда пользователь изменил тему или системные цвета.Это событие также срабатывает, когда вы не находитесь рядом с машиной, и Windows автоматически блокирует рабочую станцию.Это объясняет утреннее похмелье.

В результате тупиковой ситуации возникла проблема с многопоточностью, класс SystemEvents запускает событие не в том потоке.Что вызвано проблемой инициализации в вашей программе.Типичный триггер не создает первое окно в главном потоке, которое запутывает SystemEvents.Он пытается запустить событие в том же потоке снова, но его больше нет.Или он скопировал SynchronizationContext.Current до того, как он был инициализирован Winforms.В любом случае, событие будет запущено в потоке потоков вместо основного потока пользовательского интерфейса.Это смертельно.

Распространено, например, когда вы создаете свой собственный экран-заставку.Вместо этого используйте встроенную поддержку .

...