首頁 > 後端開發 > C++ > 為什麼我的非同步 C# 方法在存取任務結果時掛起?

為什麼我的非同步 C# 方法在存取任務結果時掛起?

Barbara Streisand
發布: 2025-01-08 13:47:42
原創
951 人瀏覽過

Why Does My Asynchronous C# Method Hang When Accessing Task Results?

C#非同步方法在存取Task結果時掛起的原因

使用C#的asyncawait關鍵字進行非同步程式設計時,某些結構可能會導致意外行為和潛在的死鎖。

考慮以下場景:一個多層應用程式使用擴充的資料庫實用程式方法ExecuteAsync,該方法非同步執行SQL查詢並傳回結果。中間層方法GetTotalAsync呼叫ExecuteAsync來檢索資料並將結果儲存在asyncTask變數中。最後,UI操作嘗試使用asyncTask.Result同步存取結果。但是,應用程式無限期掛起。

死鎖的原因

問題源自於在GetTotalAsync方法中使用await。預設情況下,非同步方法的延續在啟動方法的相同SynchronizationContext上調度。在這種情況下,當在UI執行緒上使用await時,延續(return result;)也計劃在UI執行緒上運行。

當在UI執行緒上呼叫asyncTask.Result時,它會在Task完成時阻塞執行緒。但是,在UI執行緒上調度的延續直到asyncTask.Result完成才能執行。這會建立一個死鎖,兩個執行緒都無法繼續執行。

為了解決這個死鎖,有幾個方法:

1. 刪除Async關鍵字:

消除await的使用,並將ExecuteAsyncGetTotalAsync方法重寫為不等待的純非同步方法:

<code class="language-csharp">public static Task<T> ExecuteAsync<T>(this OurDBConn dataSource, Func<OurDBConn, T> function)
{
    // ... (代码保持不变)
}

public static Task<ResultClass> GetTotalAsync(...)
{
    // ... (代码保持不变)
}</code>
登入後複製

2. 使用ConfigureAwait:

使用ConfigureAwait(false)指定延續不應在UI執行緒上調度:

<code class="language-csharp">public static async Task<ResultClass> GetTotalAsync(...)
{
    var resultTask = this.DBConnection.ExecuteAsync<ResultClass>(
        ds => ds.Execute("select slow running data into result"));

    return await resultTask.ConfigureAwait(false);
}</code>
登入後複製

注意,這種方法需要在所有可能導致死鎖的await操作上明確指定ConfigureAwait(false)

3. 使用SynchronizationContext:

為非同步操作建立一個特定的SynchronizationContext,並確保所有await操作都使用該上下文,從而防止與UI執行緒發生衝突。

以上是為什麼我的非同步 C# 方法在存取任務結果時掛起?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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