C# 死鎖 TaskCompletionSource


在異步轉同步時,使用不當容易造成死鎖(程序卡死)

看如下案例:

有一個異步方法

1     private static async Task TestAsync()
2     {
3         Debug.WriteLine("異步任務start……");
4         await Task.Delay(2000);
5         Debug.WriteLine("異步任務end……");
6     }

在執行如上異步方法時,嘗試將其轉換為同步方法

按照官方文檔《使用任務簡化異步編程》,TaskCompletionSource使用步驟:

  1. 獲取var sourceTask =TaskCompletionSource.Task,
  2. 等待此sourceTask結果-sourceTask.Result
  3. 設置設置sourceTask.Result的結果值
 1     private void TaskCompleteSourceDead_OnClick(object sender, RoutedEventArgs e)
 2     {
 3         AwaitByTaskCompleteSource(TestAsync());
 4         Debug.WriteLine($"4. TaskCompleteSource_OnClick end");
 5     }
 6     private void AwaitByTaskCompleteSource(Task task)
 7     {
 8         var taskCompletionSource = new TaskCompletionSource<object>();
 9         var taskFromSource = taskCompletionSource.Task;
10         task.ContinueWith(action =>
11         {
12             taskCompletionSource.SetResult(true);
13         });
14         var task1Result = taskFromSource.Result;
15         Debug.WriteLine($"3. AwaitByTaskCompleteSource end:{task1Result}");
16     }

但是,以上邏輯執行時,界面會卡死!卡死效果如下,卡死的時候點擊界面其它按鈕無任何反應。

為何會死鎖?

猜測可能與Task.wait()類似的死鎖,詳細如下:

  1. UI線程調用子線程並等待子線程結果,
  2. 子線程執行過程中,切換到了UI線程(因為TestAsync是在UI線程運行的)
  3. 從而導致兩個線程均處在阻塞狀態(死鎖)

 

關鍵字:死鎖、TaskCompletionSource

 

參考資料:

同步轉異步
異步轉同步
死鎖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM