2011-07-06 76 views
5

私は、モードレスWin32フォームをホストするWPFアプリケーションを持っています。 VNCをマシンに接続するか取り外すまで、すべてがスムーズに実行されます。その後、アプリケーションはデッドロックします。何も再描画されず、ユーザーの操作に反応しません。私はWinDbgのを使用して、スタックトレースを見てきました:DisplaySettingsChangingのWPF interopデッドロック

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は/デタッチが順番にメインスレッドにメッセージを送信し、System.Windows.Forms.Control.Invokeを使用して、いくつかのイベントを呼び出そうとしOnDisplaySettingsChangingイベントを発生させ添付する応答を待ちます。しかし、これはすべてメインスレッドで発生するため、メッセージループは決してメッセージを取得せず、待機は返されません。

EnableSystemEventsThreadAffinityCompatibility(これは本質的にControl.Invoke呼び出しをバイパスします)を使用して回避策を見つけましたが、汚れたハックのように感じます。

このようなことが起こったことはありますか?

SystemEventsクラスは、メッセージがメイン(STA)スレッドに到着したときにControl.Invokeを使用する理由を知りましたか?

編集:コメント欄での質問への回答:VNCせずにディスプレイの設定(例えば、解像度)を変更するとき

  • 同じことが起こるのでしょうか? - > No.
  • VNCで複数の異なるバージョン(hte最新版を含む)でも同じことが起こりますか? - >私は最新のバージョン1.0.9.5を試してみました。
  • WPFアプリ、コントロール、またはWin32コントロールに関するその他の詳細は? - > WPFのメインウィンドウとモードレスのWinFormsフォームがあります。
+0

いくつかのQ: '1 'VNCを使わずにディスプレイ設定(resなど)を変更しても同じことが起こりますか? '2)' VNC上のいくつかの異なるバージョン(hte最新版を含む)でも同じことが起こりますか? '3)' WPFアプリケーション、コントロール、またはWin32コントロールについてのその他の詳細は? –

+1

これはプログラムの初期化の問題です。カスタムスプラッシュ画面に注意してください。 –

+0

@Hans Passant:ありがとう!私は 'ISynchronizeInvoke'が必要なので起動時に' Form'を作成しました。これが問題の原因でした。私はそれを 'Control'に変更しました。そして、すべてがスムーズに機能します。私はそれを受け入れることができるように、あなたのコメントを回答として投稿してください。 – Niki

答えて

1

これはプログラムの初期化の問題です。カスタムスプラッシュ画面に注意してください。最初のイベントサブスクリプションがメインスレッドで発生しない場合、間違ったスレッドで通知が発生します。これは、奇妙な絵画の人工物から完全なデッドロックまで、あらゆる種類の厄介な問題を引き起こす可能性があります。いくつかの標準Winformsコントロールは、SystemEventsを使用して、Windowsのテーマやシステムの色が変更されたときにいつ再描画する必要があるかを知っていることに注意してください。

1つの回避策は、何か他のことが行われる前に、Main()メソッドでダミーのイベントハンドラを明示的にサブスクライブすることです。

関連する問題