在异步转同步时,使用不当容易造成死锁(程序卡死)
看如下案例:
有一个异步方法
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
参考资料:
同步转异步
异步转同步
死锁