zoukankan      html  css  js  c++  java
  • async/await的一些用法

    普通函数

    string Func() 
    {  
      string x = X();  
      string y = Y();  
      string z = Z();
    
      return x + y + z; 
    }
    

     X(), Y(), Z()内部都Sleep 10s, 则Func()耗时30s

    异步函数

    async string FuncAsync()
    {
    	string x = await XAsync();
    	string y = await YAsync();
    	string z = await ZAsync();
    
    	return x + y + z;
    }
    

    假设 XAsync(), YAsync(), YAsync()内部都Sleep10s, 则FuncAync()还是耗时多少呢?

    整个FuncAsync会被拆成如下部分:

    1. FuncAsync-开始部分();
    2. XAsync();
    3. FuncAsync-中间部分1();
    4. YAsync();
    5. FuncAsync-中间部分2();
    6. ZAsync();
    7. FuncAsync-结束部分();

    这些部分会被.NET同步上下文SynchronizationContext在同一个线程依次执行,如下:

    1. 同步上下文执行 FuncAsync-开始部分();
    2. 同步上下文执行 XAsync(); //内部调用了Sleep10s, 要10s才返回
    3. 同步上下文执行 FuncAsync-中间部分1();
    4. 同步上下文执行 YAsync();//内部调用了Sleep10s, 要10s才返回
    5. 同步上下文执行 FuncAsync-中间部分2()
    6. 同步上下文执行 ZAsync();//内部调用了Sleep10s, 要10s才返回
    7. 同步上下文执行 FuncAsync-结束部分();

    所以耗时时间还是30s

    假设 XAsync(), YAsync(), YAsync()内部都把Sleep10s用Task.Run()都包起来返回

    1. 同步上下文执行 FuncAsync-开始部分();
    2. 同步上下文执行 XAsync(); 立刻返回, 在另一个线程执行Sleep(10)
    3. 同步上下文等待 但可以执行其他异步任务, 如果是Winform的话UI不会卡
    4. 后台线程10s结束告诉同步上下文继续执行
    5. 同步上下文执行 FuncAsync-中间部分1();
    6. 同步上下文执行 YAsync(); 立刻返回, 在另一个线程执行Sleep(10)
    7. 同步上下文等待 但可以执行其他异步任务, 如果是Winform的话UI不会卡
    8. 后台线程10s结束告诉同步上下文继续执行
    9. 同步上下文执行 FuncAsync-中间部分2()
    10. 同步上下文执行 ZAsync(); 立刻返回, 在另一个线程执行Sleep(10)
    11. 同步上下文等待 但可以执行其他异步任务, 如果是Winform的话UI不会卡
    12. 后台线程10s结束告诉同步上下文继续执行
    13. 同步上下文执行 FuncAsync-结束部分();

    所以FuncAsync总耗时时间还是30s,优点是UI线程不会被卡住, UI线程不是被FuncAsync一个任务占有,其他异步任务也能在UI线程上执行,真正等待的任务都运行在后台线程。

    下面这个版本,FuncAsync()执行的时间才是10s

    async string FuncAsync()
    {
    	var taskX = XAsync();
    	var taskY = YAsync();
    	var taskZ =  ZAsync();
    
    	await Task.WhenAll(taskX, taskY, taskZ);
    
    	return taskX.Result + taskY.Result + taskZ.Result;
    }
    

    如果在XAsync()里调用Task.Result同步等待会怎样?

    1. 同步上下文执行 FuncAsync-开始部分();
    2. 同步上下文执行 XAsync();    
      1.   XAsync() 调用 YAsync()  返回task             
        1.   YAsync() 开启后台线程sleep10s    
      2.   XAsync()等待task.Result    
    3. 后台线程10s结束告诉同步上下文继续

    XAsync要等待的结果(task.Result),需要同步上下文返回,

    虽然后台线程已经同步上下文结果了,但同步上下文此时却还在执行XAsync的过程中.

    互相等待,于是产生死锁.

    举个形象的例子:

    1. 医生Doctor给病人Patients看病, 病人必须先排队,按次序来。
    2. 轮到某个病人PatientX时要某项检查报告,病人说,等我一下,检查报告在我老婆手里,我打电话让她送来。
    3. 于是医生Doctor和病人PatientX开始等待, 左等右等不来。
    4. 其实几分钟后病人的老婆PatientXWife已经把检查报告送来了, 只不过她拿着检查报告在队列里等。
  • 相关阅读:
    感光板制作问答
    游戏外挂技术分析(转)
    div 显示和隐藏
    c# 构造sql语句
    Iframe自动适应高度
    .net web图表类
    通讯录从Database导出vCard格式
    winform通过HttpWebRequest(post方式)上传文件和传递参数
    c# CSV读入DataSet
    模拟器显示屏上方的信号和电池图标不显示设置
  • 原文地址:https://www.cnblogs.com/mrfangzheng/p/7294459.html
Copyright © 2011-2022 走看看