DisplaySettingsChanging上的WPF互操作死锁

Nik*_*iki 5 .net wpf winforms-interop winforms

我有一个WPF应用程序,托管一个无模式的Win32表单.一切都顺利进行,直到我将VNC连接或拆卸到机器上.然后应用程序死锁:它不再重绘任何东西,不会对用户交互作出反应.我使用WinDbg查看了堆栈跟踪:

0012f03c 792b6865 System.Threading.WaitHandle.WaitOne(Int32, Boolean)
0012f050 7b6f1a4f System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle)
0012f064 7ba2d68b System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean)
0012f104 7b6f33ac System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[])
0012f138 7b920bd7 System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback, System.Object)
0012f150 7a92ed62 Microsoft.Win32.SystemEvents+SystemEventInvokeInfo.Invoke(Boolean, System.Object[])
0012f184 7a92dc8f Microsoft.Win32.SystemEvents.RaiseEvent(Boolean, System.Object, System.Object[])
0012f1d0 7a92daec Microsoft.Win32.SystemEvents.OnDisplaySettingsChanging()
0012f1e0 7a574c9f Microsoft.Win32.SystemEvents.WindowProc(IntPtr, Int32, IntPtr, IntPtr)
0012f1e4 003c20dc [InlinedCallFrame: 0012f1e4] 
0012f3a8 57843a57 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
0012f3f8 57843129 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
0012f404 578430cc System.Windows.Threading.Dispatcher.Run()
0012f410 55bed46e System.Windows.Application.RunDispatcher(System.Object)
0012f41c 55bec76f System.Windows.Application.RunInternal(System.Windows.Window)
0012f440 55bd3aa6 System.Windows.Application.Run(System.Windows.Window)
0012f450 55bd3a69 System.Windows.Application.Run()
Run Code Online (Sandbox Code Playgroud)

显然,VNC附加/分离引发一个OnDisplaySettingsChanging事件,该事件又试图使用一个事件来调用某个事件System.Windows.Forms.Control.Invoke,该事件向主线程发送一条消息然后等待响应.但由于这一切都发生在主线程中,消息循环永远不会得到消息,等待永远不会返回.

我找到了一个使用的解决方法EnableSystemEventsThreadAffinityCompatibility(基本上绕过了Control.Invoke调用),但感觉就像一个肮脏的黑客.

有人见过这样的事吗?

有人知道为什么当消息到达主(STA)线程时,SystemEvents类会使用Control.Invoke它(它确实,我检查过)?

编辑:评论中的问题的答案:

  • 在没有VNC的情况下更改显示设置(例如res)时是否会发生同样的事情? - >不.
  • 在VNC上有几个不同的版本会发生同样的事情(包括最新的)吗? - >我只尝试过最新版本1.0.9.5.
  • 有关WPF应用程序,控件或Win32控件的任何其他详细信息? - >有一个WPF主窗口和一个无模式的WinForms表单.

Han*_*ant 1

这是一个程序初始化问题。注意自定义启动画面。如果第一个事件订阅没有发生在主线程上,那么它将在错误的线程上触发通知。这可能会导致各种令人讨厌的问题,从奇怪的绘画伪影到彻底的僵局。请注意,当 Windows 主题或系统颜色更改时,一些标准 Winforms 控件将使用 SystemEvents 来了解何时应重新绘制自己。

一种解决方法是在执行其他操作之前在 Main() 方法中显式订阅虚拟事件处理程序。