async,await执行流看不懂?看完这篇以后再也不会了

内容简介:昨天有朋友在公众号发消息说看不懂await,async执行流,其实看不懂太正常了,因为你没经过社会的毒打,没吃过牢饭就不知道自由有多重要,没生过病就不知道健康有多重要,没用过ContinueWith就不知道await,async有多重要,下面我举两个案例佐证一下?写了这么多年的程序,相信大家都知道连接数据库少不了这几个对象,DbConnection,DbCommand,DbDataReader等等。。先来看看ContinueWith在连接数据库时嵌套过深的尴尬。这个时期的代码没有什么好说的,都是程式代码,一

本文转载自:http://www.cnblogs.com/huangxincheng/p/12752849.html,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有。

昨天有朋友在公众号发消息说看不懂await,async执行流,其实看不懂太正常了,因为你没经过社会的毒打,没吃过牢饭就不知道自由有多重要,没生过病就不知道健康有多重要,没用过ContinueWith就不知道await,async有多重要,下面我举两个案例佐证一下?

一:案例一 【嵌套下的异步】

写了这么多年的程序,相信大家都知道连接 数据库 少不了这几个对象,DbConnection,DbCommand,DbDataReader等等。。先来看看ContinueWith在连接数据库时嵌套过深的尴尬。

1. NetFramework 4.0之前的写法

这个时期的代码没有什么好说的,都是程式代码,一撸到底,简洁明了。

public static int SyncGetCount()         {             using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))             {                 connection.Open();                 using (var command = connection.CreateCommand())                 {                     command.CommandText = "select count(1) from messages";                      var count = command.ExecuteScalar();                      Console.WriteLine($"记录条数:{count}");                      return Convert.ToInt32(count);                 }             }         }  -------- output -------------  记录条数:75896

2. NetFramework 4.0下ContinueWith的写法

当年异步和并发编程概念特别火,火热度参考现在的直播带货,这个时期的C#率先使用新的Task一网兜,在数据库操作的几大类中开始有了Async结尾的方法,如OpenAsync,ExecuteScalarAsync,ReadAsync 等等,但遗憾的是那时写异步,只能像下面这样写。

public static Task<object> ContinueWithGetCount()         {             var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;");              var task = connection.OpenAsync().ContinueWith(t1 =>              {                  var command = connection.CreateCommand();                   command.CommandText = "select count(1) from messages";                   return command.ExecuteScalarAsync().ContinueWith(t2 =>                                                                   {                                                                       command.Dispose();                                                                       connection.Dispose();                                                                        Console.WriteLine($"记录条数:{t2.Result}");                                                                        return t2.Result;                                                                   });              }).Unwrap();               return task;         }  -------- output -------------  记录条数:75896

相比同步代码,这异步代码写的是不是很憋屈,为了应对渐进式的Async方法,我不得不进行ContinueWith的深层嵌套,如果Async更多,那对可读性将是毁灭性的打击,这就是所谓的回调地狱。

3. NetFramework 4.5 下 await,async的写法

写到这里让我想起了邢老大的那本自传书《左手梦想,右手疗伤》,这苦这心酸只有真正经历过的人才会懂,没有人能够随随便便成功,接下来大家的期望就是如何做到有同步式的代码又有异步功效,鱼和熊掌我都要,当然是可以的,看看如何用await,async进行改造。

public static async Task<int> AsyncGetCount()         {             using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))             {                 await connection.OpenAsync();                 using (var command = connection.CreateCommand())                 {                     command.CommandText = "select count(1) from messages";                      var count = await command.ExecuteScalarAsync();                      Console.WriteLine($"记录条数:{count}");                      return Convert.ToInt32(count);                 }             }         }  -------- output -------------  记录条数:75896

上面这代码太简洁了,眼花的朋友还以为是同步代码呢? 改造的地方也仅仅是方法签名处加上一个async,异步方法前加上await,相当于痛苦版的ContinueWith。

二:案例二 【循环下的异步】

上一个案例只是使用ExecuteScalarAsync从数据库中读取一个值来得到表中的记录数,在业务开发中更多的是使用ExecuteReader从数据库中获取批量记录,这个就涉及到了如何在循环中使用异步,想想就太苦难了(┬_┬)。

1. NetFramework 4.0之前的写法

这里我从messages表中读取5条记录,然后输出到控制台,详细代码如下:

public static List<string> SyncGetMessageList()         {             var messageList = new List<string>();             using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))             {                 connection.Open();                 using (var command = connection.CreateCommand())                 {                     command.CommandText = "select message from messages limit 5;";                     using (var reader = command.ExecuteReader())                     {                         while (reader.Read())                         {                             messageList.Add(reader.GetString("message"));                         }                     }                 }             }             messageList.ForEach(Console.WriteLine);             return messageList;         }   ------------- output ----------------  你需要忘记失去的,感激拥有的,和期待将至的。 以前的找不到了。 对于编译错误,删除Pods文件夹然后重新pod install已经成为经验。次。 Hello,Is there anyone here? 放松心情

2. NetFramework 4.0下ContinueWith的写法

要想用ContinueWith完成这功能,最简单有效的办法就是使用递归,用递归的方式把若干个ContinueWith串联起来,而要用递归的话还要单独定义一个方法,写的有点乱,大家将就着看吧。

public class Program     {         public static void Main(string[] args)         {             var task = ContinueWithAsyncGetMessageList();              task.Result.ForEach(Console.WriteLine);              Console.Read();         }          public static Task<List<string>> ContinueWithAsyncGetMessageList()         {             var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;");              var task = connection.OpenAsync().ContinueWith(t1 =>              {                  var messageList = new List<string>();                   var command = connection.CreateCommand();                   command.CommandText = "select message from messages limit 5;";                   return command.ExecuteReaderAsync().ContinueWith(t2 =>                  {                      var reader = (MySqlDataReader)t2.Result;                      return GetMessageList(reader, messageList).ContinueWith(t3 =>                      {                          reader.Dispose();                          command.Dispose();                          connection.Dispose();                      });                  }).Unwrap().ContinueWith(t3 => messageList);               }).Unwrap();              return task;         }          /// <summary>         /// 采用递归处理循环         /// </summary>         /// <param name="reader"></param>         /// <param name="messageList"></param>         /// <returns></returns>         public static Task<List<string>> GetMessageList(MySqlDataReader reader, List<string> messageList)         {             var task = reader.ReadAsync().ContinueWith(t =>               {                   if (t.Result)                   {                       var massage = reader.GetString("message");                       messageList.Add(massage);                       return GetMessageList(reader, messageList);                   }                   else                   {                       return Task.FromResult(new List<string>());                   }               }).Unwrap();              return task;         }     }  ------------ output ---------------- 你需要忘记失去的,感激拥有的,和期待将至的。 以前的找不到了。 对于编译错误,删除Pods文件夹然后重新pod install已经成为经验。次。 Hello,Is there anyone here? 放松心情

在递归下探的过程中把messageList集合给填满了,而后将messageList返回给调用端即可,如果没看明白,我画一张图吧!

async,await执行流看不懂?看完这篇以后再也不会了

3. NetFramework 4.5 下 await,async的写法

:smile:,刚刚是不是噩梦般经历,救世主来啦,还是要鱼和熊掌一起兼得。

public static async Task<List<string>> AsyncGetMessageList()         {             var messageList = new List<string>();             using (var connection = new MySqlConnection("server=xxx.xxx.xxx.xxx;userid=xxx;password=xxx;database=xxx;charset=utf8;port=3306;"))             {                 await connection.OpenAsync();                 using (var command = connection.CreateCommand())                 {                     command.CommandText = "select message from messages limit 5;";                     using (var reader = await command.ExecuteReaderAsync())                     {                         while (await reader.ReadAsync())                         {                             messageList.Add(reader["message"].ToString());                         }                     }                 }             }             return messageList;         }  ------------ output ---------------- 你需要忘记失去的,感激拥有的,和期待将至的。 以前的找不到了。 对于编译错误,删除Pods文件夹然后重新pod install已经成为经验。次。 Hello,Is there anyone here? 放松心情

天底下还有如此简洁的代码就可以实现ContinueWith那种垃圾般代码所实现的功能,我都想仰天长啸,我太难了。

三:总结

还是那句话,你没有被伤过,永远不会体会到那种刻骨铭心的痛。

如您有更多问题与我互动,扫描下方进来吧~

async,await执行流看不懂?看完这篇以后再也不会了 async,await执行流看不懂?看完这篇以后再也不会了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

async,await执行流看不懂?看完这篇以后再也不会了

关注我们,获取更多IT资讯^_^

为你推荐:

  • GuiLite 1.2 发布:妈妈再也不用担心我看不懂 GuiLite 了
  • Google Play新增应用内翻译功能:再也不用担心看不懂英文简介了
  • 系统负载看不懂?
  • 这篇 ReentrantLock 看不懂?加我我给你发红包
  • 有了这个开源项目,再也不会忘记 Linux 命令啦~

相关软件推荐:

  • Python 系统任务执行程序 Invoke
  • UDP 以太网 EthUDP
  • HTTP 流量工具 Secihttp
  • 元命令行工具 keep
  • 开放实时以太网 ORTE

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

async-await tomcat启动不了 nginx 访问不了 查看oracle 文件上传不了 javascript-async-await .net-async-await github打不开 await ubuntu 查看文件 async oracle 执行计划 tomcat不能启动 查看centos版本 postgres查看触发器 mysql查看数据库 postgresql查看触发器 nginx 查看连接数 f#-async async-loading dispatch-async async-iterator oracle执行存储过程 db2执行存储过程 html5-async io-async spring-async async-safe devise-async dart-async async-components jasmine-async php后台 struts2流程 winrt-async react-async async-ctp node-async async-workflow async-onprogressupdate scala 运行 运行groovy db2银行 code-splitting-async android-async-http chrome-extension-async db2命令行 ubuntu命令行 delphi7完美经典 perl怎么运行

async,await执行流看不懂?看完这篇以后再也不会了