在非同步轉同步時,使用不當容易造成死鎖(程式卡死) 看如下案例: 有一個非同步方法 在執行如上非同步方法時,嘗試將其轉換為同步方法 按照官方文檔《使用任務簡化非同步編程》,TaskCompletionSource使用步驟: 但是,以上邏輯執行時,界面會卡死!卡死效果如下,卡死的時候點擊界面其它按鈕無任何反應 ...
在非同步轉同步時,使用不當容易造成死鎖(程式卡死)
看如下案例:
有一個非同步方法
1 private static async Task TestAsync() 2 { 3 Debug.WriteLine("非同步任務start……"); 4 await Task.Delay(2000); 5 Debug.WriteLine("非同步任務end……"); 6 }
在執行如上非同步方法時,嘗試將其轉換為同步方法
按照官方文檔《使用任務簡化非同步編程》,TaskCompletionSource使用步驟:
- 獲取var sourceTask =TaskCompletionSource.Task,
- 等待此sourceTask結果-sourceTask.Result
- 設置設置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()類似的死鎖,詳細如下:
- UI線程調用子線程並等待子線程結果,
- 子線程執行過程中,切換到了UI線程(因為TestAsync是在UI線程運行的)
- 從而導致兩個線程均處在阻塞狀態(死鎖)
關鍵字:死鎖、TaskCompletionSource