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