昨天有同伙在民众号发消息说看不懂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从数据库中获取批量纪录,这个就涉及到了若何在循环中使用异步,想想就太苦难了(┬_┬)。
代理模式是什么?如何在 C# 中实现代理模式
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返回给挪用端即可,若是没看明了,我画一张图吧!
3. NetFramework 4.5 下 await,async的写法
,刚刚是不是噩梦般履历,救世主来啦,照样要鱼和熊掌一起兼得。
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那种垃圾般代码所实现的功效,我都想仰天长啸,我太难了。
三:总结
照样那句话,你没有被伤过,永远不会体会到那种铭肌镂骨的痛。
如您有更多问题与我互动,扫描下方进来吧~
原创文章,作者:admin,如若转载,请注明出处:https://www.2lxm.com/archives/5779.html