【问题标题】:How to deal with this C# hang invloving SystemEvents.OnUserPreferenceChanged如何处理这个 C# 挂起 invloving SystemEvents.OnUserPreferenceChanged
【发布时间】:2011-11-29 16:29:51
【问题描述】:

我的 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)  

【问题讨论】:

    标签: c# multithreading .net-2.0


    【解决方案1】:

    控件订阅此事件,以便在用户更改主题或系统颜色时重绘自己。当您不靠近机器并且 Windows 自动锁定工作站时,也会触发此事件。这解释了宿醉后的早晨。

    死锁是由线程问题引起的,SystemEvents 类在错误的线程上触发事件。这是由程序中的初始化问题引起的。典型的触发器不是在主线程上创建第一个窗口,这会使 SystemEvents 感到困惑。它试图再次在同一个线程上触发一个事件,但它不再存在了。或者它在 Winforms 初始化之前复制了 SynchronizationContext.Current。无论哪种方式,该事件都将在线程池线程而不是主 UI 线程上触发。那是致命的。

    例如,在您实现自己的启动画面时很常见。请改用built-in support

    【讨论】:

    • 感谢@Hans 的回复。是的,我的表单中有一个闪屏。这是否意味着我应该在该表单被处置之前从该初始屏幕表单中取消订阅 SystemEvents?
    • 不,退订不能解决问题,你也不能。是订阅引发了问题。
    • 关于 SystemEvents 类引起的问题,请参阅 this answer 中的 CheckSystemEventsHandlersForFreeze() 函数,它可以帮助找到根本原因,即在错误的线程上创建了哪些特定控件,从而导致冻结。
    猜你喜欢
    • 2012-05-13
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 2020-06-05
    • 2020-04-11
    相关资源
    最近更新 更多