在异步转同步时,使用不当容易造成死锁(程序卡死)

看如下案例:

有一个异步方法

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