zoukankan      html  css  js  c++  java
  • 第十节:利用async和await简化异步编程模式的几种写法

    一. async和await简介

    PS:简介

    1. async和await这两个关键字是为了简化异步编程模型而诞生的,使的异步编程跟简洁,它本身并不创建新线程,但在该方法内部开启多线程,则另算。

    2. 这两个关键字适用于处理一些文件IO操作。

    3. 好处:代码简介,把异步的代码写成了同步的形式,提高了开发效率。

     坏处:如果使用同步思维去理解,容易出问题,返回值对不上。

    二. 几种用法

    情况1:当只有async,没有await时,方法会有个警告,和普通的多线程方法没有什么区别,不存在线程等待的问题。

    代码实践:

     1  private static async void Test1()
     2         {
     3             //主线程执行
     4             Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
     5             //启动新线程完成任务
     6             Task task = Task.Run(() =>
     7             {
     8                 Console.WriteLine("子线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
     9                 Thread.Sleep(3000);
    10                 Console.WriteLine("子线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    11             });
    12             //主线程执行
    13             Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    14         }

    代码结果:

    情况2:不推荐void返回值,使用Task来代替Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用,async Void 不行。

    代码实践:

     1         /// <summary>
     2         /// 不推荐void返回值,使用Task来代替
     3         /// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。async Void 不行
     4         /// </summary>
     5         private static async void Test2()
     6         {
     7             //主线程执行
     8             Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
     9             //启动新线程完成任务
    10             Task task = Task.Run(() =>
    11             {
    12                 Console.WriteLine("子线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
    13                 Thread.Sleep(3000);
    14                 Console.WriteLine("子线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    15             });
    16             await task;   //等待子线程执行完毕,方可执行后面的语句
    17             Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    18         }

    代码结果:

     

    情况3:async Task == async void。 区别:Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用,async Void 不行。

    代码实践:

     1          /// <summary>
     2         /// 无返回值  async Task == async void
     3         /// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用,async Void 不行
     4         /// </summary>
     5         private static async Task Test3()
     6         {
     7             //主线程执行
     8             Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
     9             //启动新线程完成任务
    10             Task task = Task.Run(() =>
    11             {
    12                 Console.WriteLine("子线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
    13                 Thread.Sleep(3000);
    14                 Console.WriteLine("子线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    15             });
    16             await task;   //等待子线程执行完毕,方可执行后面的语句
    17             Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    18         }

    代码结果:

     

    情况4和情况5:说明要使用子线程中的变量,一定要等子线程执行结束后再使用。

    代码实践:

     1         /// <summary>
     2         /// 带返回值的Task,要使用返回值,一定要等子线程计算完毕才行
     3         /// </summary>
     4         /// <returns></returns>
     5         private static async Task<long> Test4()
     6         {
     7             //主线程执行
     8             Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
     9             long result = 0;
    10             //启动新线程完成任务
    11             Task task = Task.Run(() =>
    12             {
    13                 for (long i = 0; i < 100; i++)
    14                 {
    15                     result += i;
    16                 }
    17             });
    18             await task;   //等待子线程执行完毕,方可执行后面的语句
    19             Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    20             Console.WriteLine("result:{0}", result);
    21             return result;
    22         }
     1         /// <summary>
     2         /// 带返回值的Task,要使用返回值,一定要等子线程计算完毕才行
     3         /// 与情况四形成对比,没有等待,最终结果不准确
     4         /// </summary>
     5         /// <returns></returns>
     6         private static Task<long> Test5()
     7         {
     8             //主线程执行
     9             Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
    10             long result = 0;
    11             //启动新线程完成任务
    12             TaskFactory taskFactory = new TaskFactory();
    13             Task<long> task = taskFactory.StartNew<long>(() =>
    14             {
    15                 for (long i = 0; i < 100; i++)
    16                 {
    17                     result += i;
    18                 }
    19                 return 1;
    20             });
    21             Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
    22             Console.WriteLine("result:{0}", result);
    23             return task;
    24         }

    代码结果:

       以上两种情况,第一种情况含有线程等待的结果为4950,第二个情况么有线程等待,结果不准确(即共享变量竞用问题)。

  • 相关阅读:
    什么样的代码称得上是好代码?
    九年程序人生 总结分享
    Docker入门 第一课 --.Net Core 使用Docker全程记录
    阿里云 Windows Server 2012 r2 部署asp.net mvc网站 平坑之旅
    Visual studio 2015 Community 安装过程中遇到问题的终极解决
    Activiti6.0 spring5 工作流引擎 java SSM流程审批 项目框架
    java 进销存 库存管理 销售报表 商户管理 springmvc SSM crm 项目
    Leetcode名企之路
    24. 两两交换链表中的节点
    21. 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/8283956.html
Copyright © 2011-2022 走看看