C# 死鎖 TaskCompletionSource

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

看以下案例:異步

有一個異步方法async

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

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

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

  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     }

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

爲什麼會死鎖?code

猜想可能與Task.wait()相似的死鎖,詳細以下:blog

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

 

關鍵字:死鎖、TaskCompletionSource文檔

相關文章
相關標籤/搜索