簡體   English   中英

為什么 await Task.Run() 不會返回同一個線程?

[英]Why would await Task.Run() not return to the same thread?

我遇到了一種情況,讓我覺得我不像我想象的那樣理解 async / await 機制。

我有一個 Windows 桌面應用程序,主要是 WPF 但使用 WinForms 主機來顯示第三方 COM2668ACDE6311BD459 加載 COM object 的過程非常緩慢,所以我一直在嘗試將這些對象的創建和初始化移到一個任務中,以便在工作發生時釋放 UI,但我發現在某些情況下,當await Task.Run() 返回,它不在 UI 線程上。 結果,當我在任務返回后更改 WinForms 主機上的 Visible 屬性時,由於跨線程調用,它會拋出。

調用 function 如下所示:

public async Task<bool> LoadPreview(string filePath)
{
    bool result;

    try
    {
        await _semaphore.WaitAsync();
        result = await Task.Run(() => CreateAndInitializePreviewer(filePath));

        if (result)
        {
            Visible = false; // <-- occasionally crashes because I'm not on the UI thread
            _currentHandler.DoPreview();
            Visible = true;
        }
    }
    finally
    {
        _semaphore.Release();
    }

    return result;
}

CreateAndInitializePreviewer 中的代碼沒有任何 async / await 調用。 我已經驗證了在調用 Task.Run() 之前我總是在 UI 線程上。

關於我應該尋找什么的任何建議都會導致 await Task.Run() 回到不同的線程? 任何想法表示贊賞。

加載 COM object 的過程非常緩慢,所以我一直在嘗試將這些對象的創建和初始化轉移到一個任務中,以便在工作發生時釋放 UI

這可能行不通,除非您的 COM object 是自由線程的(這不太可能)。 If you want to push that work off your UI thread, you'll probably need to create a separate STA thread to hold the COM object and marshal calls to/from that thread - meaning all calls to that COM object, since it would live in另一個 STA 線程。 在 WPF 中創建第二個 UI (STA) 線程相當簡單 這有點難,但在 WinForms 中仍然可行。

關於我應該尋找什么的任何建議都會導致 await Task.Run() 回到不同的線程?

是的。 如果不是null ,則await將捕獲SynchronizationContext.Current ,在這種情況下它不應該null 它應該是DispatcherSynchronizationContext的實例(通過向 WPF 調度程序發送消息繼續執行)或WinFormsSynchronizationContext (通過向 WinForms winproc 發送消息繼續執行)。

我最初的猜測是,由於 WinForms-in-WPF 架構, SynchronizationContext.Current發生了一些奇怪的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM