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中文網其他相關文章!