StaTaskScheduler と STA スレッドのメッセージ ポンピング
質問:
STA スレッドで StaTaskScheduler と BlockingCollection を使用すると、メッセージ ポンピングが不足しているため、デッドロックが発生します。
解決策:
メッセージ ポンピング機能を備えたカスタム同期コンテキストを実装するには、MsgWaitForMultipleObjectsEx
の代わりに CoWaitForMultipleHandles
を使用します。
詳しい手順:
SynchronizationContext.Wait
をオーバーライドして、MsgWaitForMultipleObjectsEx
を使用してメッセージ ポンピングを実装し、メッセージを表示/ディスパッチします。 実装手順:
MWMO_INPUTAVAILABLE
フラグを指定した MsgWaitForMultipleObjectsEx
を使用して受信メッセージを検出します。 Wait
メソッドで PeekMessage(PM_REMOVE)
と DispatchMessage
を呼び出して、メッセージを手動でポンプします。 利点:
サンプルコード:
<code class="language-csharp">// 带有消息泵送的自定义同步上下文 class CustomSynchronizationContext : SynchronizationContext { protected override void OnWait(bool unused) { const uint QS_MASK = 0x0001; const uint MWMO_INPUTAVAILABLE = 0x0004; var nativeResult = MsgWaitForMultipleObjectsEx( 0, null, WAIT_INFINITE, QS_MASK, MWMO_INPUTAVAILABLE); var msg = new MSG(); while (true) { if (nativeResult == WAIT_OBJECT_0) break; if (PeekMessage(out msg, IntPtr.Zero, 0, 0, PM_REMOVE)) { TranslateMessage(ref msg); DispatchMessage(ref msg); } nativeResult = MsgWaitForMultipleObjectsEx(0, null, 0, QS_MASK, MWMO_INPUTAVAILABLE); } } } // 使用方法 using (var staThread = new ThreadWithAffinityContext(true, true)) { staThread.Run(async () => { // 在 STA 线程上安装自定义同步上下文 SynchronizationContext.SetSynchronizationContext(new CustomSynchronizationContext()); // 使用消息泵送的 STA 线程代码... }); }</code>
以上がStaTaskScheduler と BlockingCollection を使用して STA スレッドのデッドロックを解決するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。