5

我有一个托管无模式 Win32 表单的 WPF 应用程序。一切运行顺利,直到我将 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()

显然,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 窗体。
4

1 回答 1

1

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

一种解决方法是在 Main() 方法中显式订阅一个虚拟事件处理程序,然后再执行其他任何操作。

于 2011-07-14T18:38:17.170 回答