首頁 > 後端開發 > C++ > 如何使用 StaTaskScheduler 和 BlockingCollection 解決 STA 執行緒中的死鎖?

如何使用 StaTaskScheduler 和 BlockingCollection 解決 STA 執行緒中的死鎖?

Linda Hamilton
發布: 2025-01-11 10:33:44
原創
162 人瀏覽過

How to Resolve Deadlocks in STA Threads Using StaTaskScheduler and BlockingCollection?

StaTaskScheduler 和 STA 執行緒訊息泵送

問題:

由於缺乏訊息泵送,在 STA 執行緒上使用 StaTaskScheduler 和 BlockingCollection 時會發生死鎖。

解:

使用 MsgWaitForMultipleObjectsEx 來取代 CoWaitForMultipleHandles 實作具有訊息泵送功能的自訂同步上下文。

逐步說明:

  1. 了解問題:STA TaskScheduler 不會自動在 STA 執行緒上泵送訊息。
  2. 確定根本原因:BlockingCollection 執行的阻塞操作不會泵送訊息。
  3. 建立自訂同步上下文:重寫 SynchronizationContext.Wait 以使用 MsgWaitForMultipleObjectsEx 實作訊息泵送並檢視/分派訊息。
  4. 安裝自訂同步上下文:在 StaTaskScheduler 建立的每個 STA 執行緒上安裝自訂同步上下文。
  5. 使用自訂同步上下文:結合使用 StaTaskScheduler 和自訂同步上下文調度任務,以確保訊息泵送。

實作說明:

  • 使用有 MWMO_INPUTAVAILABLE 標誌的 MsgWaitForMultipleObjectsEx 來偵測傳入的訊息。
  • 透過在自訂同步上下文的 Wait 方法中呼叫 PeekMessage(PM_REMOVE)DispatchMessage 來手動泵送訊息。
  • 優雅地處理超時和潛在的競爭條件。

優勢:

  • 透過確保在 STA 執行緒上處理訊息來解決死鎖問題。
  • 為舊版 COM 物件維護正確的 STA 執行環境。
  • 使用後續的 await 延續時保留執行緒關聯性。

範例程式碼:

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

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板