官方和老人言,asp.net core中尽量用异步,为什么呢?接下来是个小demo,看看同步异步的差别吧,或许通过这个demo,就明白官方和老人的良苦用心了。
1、创建一个sql server的表
CREATE TABLE [dbo].[Students]( [StuNo] [varchar](50) NOT NULL, [Name] [varchar](50) NULL, [CardID] [varchar](18) NULL, [Sex] [varchar](4) NULL, [Birthday] [datetime] NULL, [ClassID] [int] NULL, CONSTRAINT [PK_dbo.Students] PRIMARY KEY CLUSTERED ( [StuNo] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
2、创建一个asp.net core api项目,5.0的
using Microsoft.AspNetCore.Mvc; using Microsoft.Data.SqlClient; using Microsoft.Extensions.Logging; using System; using System.Threading.Tasks; namespace AsyncWebAPI.Controllers { [ApiController] [Route("[controller]")] public class StudentController : ControllerBase { private readonly ILogger<StudentController> _logger; public StudentController(ILogger<StudentController> logger) { _logger = logger; } [HttpDelete("/deleteall")] public bool DeleteAll() { _logger.LogInformation("删除全部"); using var con = new SqlConnection("server=.;database=TestManageDB;uid=sa;pwd=sa;"); var sql = @"delete from [dbo].[Students]"; var cmd = new SqlCommand(sql, con); con.Open(); var result = cmd.ExecuteNonQuery(); con.Close(); return true; } [HttpPost("/addstudent")] public Student AddEntity([FromBody] Student student) { _logger.LogInformation("同步添加"); return SavaEntity(student); } Student SavaEntity(Student student) { student.StuNo = Guid.NewGuid().ToString(); using var con = new SqlConnection("server=.;database=TestManageDB;uid=sa;pwd=sa;"); var sql = @"INSERT INTO [dbo].[Students] ([StuNo] ,[Name] ,[CardID] ,[Sex] ,[Birthday] ,[ClassID] ) VALUES (@StuNo ,@Name ,@CardID ,@Sex ,@Birthday ,@ClassID )"; var cmd = new SqlCommand(sql, con); cmd.Parameters.Add(new SqlParameter { ParameterName = "@StuNo", Value = student.StuNo, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@Name", Value = student.Name, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@CardID", Value = student.CardID, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@Sex", Value = student.Sex, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@Birthday", Value = student.Birthday, SqlDbType = System.Data.SqlDbType.DateTime }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@ClassID", Value = student.ClassID, SqlDbType = System.Data.SqlDbType.Int }); con.Open(); var result = cmd.ExecuteNonQuery(); con.Close(); return student; } [HttpPost("/addstudentasync")] public async Task<Student> AddEntityAsync([FromBody] Student student) { _logger.LogInformation("异步添加"); return await SavaEntityAsync(student); } async Task<Student> SavaEntityAsync(Student student) { student.StuNo = Guid.NewGuid().ToString(); using var con = new SqlConnection("server=.;database=TestManageDB;uid=sa;pwd=sa;"); var sql = @"INSERT INTO [dbo].[Students] ([StuNo] ,[Name] ,[CardID] ,[Sex] ,[Birthday] ,[ClassID] ) VALUES (@StuNo ,@Name ,@CardID ,@Sex ,@Birthday ,@ClassID )"; var cmd = new SqlCommand(sql, con); cmd.Parameters.Add(new SqlParameter { ParameterName = "@StuNo", Value = student.StuNo, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@Name", Value = student.Name, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@CardID", Value = student.CardID, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@Sex", Value = student.Sex, SqlDbType = System.Data.SqlDbType.VarChar }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@Birthday", Value = student.Birthday, SqlDbType = System.Data.SqlDbType.DateTime }); cmd.Parameters.Add(new SqlParameter { ParameterName = "@ClassID", Value = student.ClassID, SqlDbType = System.Data.SqlDbType.Int }); await con.OpenAsync(); var result = await cmd.ExecuteNonQueryAsync(); await con.CloseAsync(); return student; } } public class Student { public string StuNo { get; set; } public string Name { get; set; } public string CardID { get; set; } public string Sex { get; set; } public DateTime Birthday { get; set; } public int ClassID { get; set; } } }
3、创建一个控制台程序,了是.net core 5.0的
using Newtonsoft.Json; using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; namespace AsyncRquestClient { class ProgramAsync { static int times = 100; static async Task Main(string[] args) { while (true) { Console.WriteLine("输入循环次数"); times = int.Parse(Console.ReadLine()); #region 同步 Console.WriteLine("-----------------同步调同步API------------------"); SyncCallSyncAPI(); Console.ReadLine(); Console.WriteLine("-----------------同步调异步API------------------"); SyncCallAsyncAPI(); Console.ReadLine(); Console.WriteLine("-----------------TaskFactory同步调同步API------------------"); TaskFactorySyncCallSyncAPI(); Console.ReadLine(); Console.WriteLine("-----------------TaskFactory同步调异步API------------------"); TaskFactorySyncCallAsyncAPI(); Console.ReadLine(); #endregion #region 异步 Console.WriteLine("-----------------异步调异步API------------------"); await AsyncCallAsyncAPI(); Console.ReadLine(); Console.WriteLine("-----------------异步调同步API------------------"); await AsyncCallSyncAPI(); Console.ReadLine(); Console.WriteLine("-----------------TaskFactory异步调异步API------------------"); await TaskFactoryAsyncCallAsyncAPI(); Console.ReadLine(); Console.WriteLine("-----------------TaskFactory异步调同步API------------------"); await TaskFactoryAsyncCallSyncAPI(); Console.ReadLine(); #endregion } } #region 异常 /// <summary> /// 异步调异步API /// </summary> /// <returns></returns> async static Task AsyncCallAsyncAPI() { var r = DeleteAllAsync().Result; Console.WriteLine($"异步调异步API开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudentasync"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine("同步调同步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } } } /// <summary> /// TaskFactory异步调异步API /// </summary> /// <returns></returns> static async Task TaskFactoryAsyncCallAsyncAPI() { var r = await DeleteAllAsync(); Console.WriteLine($"TaskFactory异步调异步开API始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { await Task.Factory.StartNew(async () => { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudentasync"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine("异步调异步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } }); } } /// <summary> /// 异步调同步API /// </summary> /// <returns></returns> async static Task AsyncCallSyncAPI() { var r = DeleteAllAsync().Result; Console.WriteLine($"异步调同步API开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudent"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine("同步调同步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } } } /// <summary> /// TaskFactory异步调同步API /// </summary> /// <returns></returns> static async Task TaskFactoryAsyncCallSyncAPI() { var r = await DeleteAllAsync(); Console.WriteLine($"TaskFactory异步调同步API开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { await Task.Factory.StartNew(async () => { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudent"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine("异步调异步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } }); } } #endregion #region 同步 /// <summary> /// 同步调同步API /// </summary> static void SyncCallSyncAPI() { var r = DeleteAllAsync().Result; Console.WriteLine($"同步调同步开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudent"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = client.SendAsync(request).Result; if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine("同步调同步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } } } static void TaskFactorySyncCallSyncAPI() { var r = DeleteAllAsync().Result; Console.WriteLine($"TaskFactory异步调同步API开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { var result = Task.Factory.StartNew(async () => { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudent"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine("异步调异步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } }).Result; } } /// <summary> /// 同步调异步API /// </summary> static void SyncCallAsyncAPI() { var r = DeleteAllAsync().Result; Console.WriteLine($"同步调异步开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudentasync"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = client.SendAsync(request).Result; if (response.IsSuccessStatusCode) { var content = response.Content.ReadAsStringAsync().Result; var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine("同步调异步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } } } static void TaskFactorySyncCallAsyncAPI() { var r = DeleteAllAsync().Result; Console.WriteLine($"TaskFactory异步调同步API开始时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff")}"); for (int i = 1; i <= times; i++) { var result = Task.Factory.StartNew(async () => { try { var student = new Student { Name = "张三" + i, Birthday = DateTime.Now, CardID = "C0000" + i, ClassID = 1, Sex = "男" }; using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Post, "addstudentasync"); request.Content = new StringContent(JsonConvert.SerializeObject(student), Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var stu = JsonConvert.DeserializeObject<Student>(content); } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine("异步调异步添加错误返回值:" + content); } } catch (Exception exc) { Console.WriteLine(exc.Message); } }).Result; } } #endregion static async Task<bool> DeleteAllAsync() { using var client = new HttpClient(); client.BaseAddress = new Uri("https://localhost:5001"); var request = new HttpRequestMessage(HttpMethod.Delete, "deleteall"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject<bool>(content); return result; } else { var content = await response.Content.ReadAsStringAsync(); Console.WriteLine("删除错误返回值:" + content); return false; } } } public class Student { public string StuNo { get; set; } public string Name { get; set; } public string CardID { get; set; } public string Sex { get; set; } public DateTime Birthday { get; set; } public int ClassID { get; set; } } }
4、在sql查询分析器中用这里的语句采集结果
--检查记录数是否完整 select count(*) from students; --查询时间隔 select datediff( millisecond, (select min(birthday) as mi from students), (select max(birthday) as ma from students) );
结果如下:
1000次请求 |
同步调同步API |
同步调异步API |
TaskFactory同步调同步API |
TaskFactory同步调异步API |
异步调异步API |
异步调同步API |
TaskFactory异步调异步API |
TaskFactory异步调同步API |
1次(毫秒) |
3190 |
3574 |
390 |
374 |
3393 |
3140 |
356 |
387 |
2次(毫秒 |
3194 |
3324 |
386 |
454 |
3370 |
3153 |
477 |
356 |
3次(毫秒 |
3350 |
3343 |
443 |
397 |
3323 |
3196 |
417 |
406 |
4次(毫秒 |
3207 |
3340 |
360 |
423 |
3206 |
3083 |
433 |
403 |
5次(毫秒 |
3214 |
3347 |
426 |
490 |
3167 |
3136 |
430 |
387 |
平均 |
3231 |
3385.6 |
401 |
427.6 |
3291.8 |
3141.6 |
422.6 |
387.8 |
客户端调用,异步优势明显;在所有的调用中,服务端的同步要优于异步。
想要更快更方便的了解相关知识,可以关注微信公众号