• 第十节:利用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,第二个情况么有线程等待,结果不准确(即共享变量竞用问题)。

  • 相关阅读:
    JavaSE--注解
    JavaSE--【JAVA】unicode为12288字符
    Spring--Spring 注入
    Spring--@configuration 和 @Bean
    JavaEE--分布式对象
    JavaSE--jdom解析之bom
    JavaEE--分布式与集群
    JavaEE--调用 WSDL -- httpclient 4.x.x
    JavaSE--RMI初识
    Redis--初识Redis
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/8283956.html
Copyright © 2020-2023  润新知