ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await
PS:异步编程的本质就是新开任务线程来处理。
约定:异步的方法名均以Async结尾。
实际上呢,异步编程就是通过Task.Run()来实现的。
了解线程的人都知道,新开一个线程来处理事务这个很常见,但是在以往是没办法接收线程里面返回的值的。所以这时候就该await出场了,await从字面意思不难理解,就是等待的意思。
执行await的方法必须是async修饰的,并且是Task的类型。 异步执行后,返回的信息存储在result属性中。但并非主进程就会卡在await行的代码上,执行到await方法之后主线程继续往下执行,无需等待新的线程执行完再继续。只有当需要用到新线程返回的result结果时,此时主进程才会等待新线程执行完并返回内容。也就是说,若无需用到新线程返回的结果,那么主进程不会等待。
async和await呢,返回类型就3种:void、Task、Task<TResult>。
1、void
如果在触发后,你懒得管,请使用 void。
void返回类型主要用在事件处理程序中,一种称为“fire and forget”(触发并忘记)的活动的方法。除了它之外,我们都应该尽可能是用Task,作为我们异步方法的返回值。
返回void,意味着不能await该异步方法,即可能出现线程阻塞,并且也无法获取exception抛出的异常,通常这些异常会导致我们的程序失败,如果你使用的是Task和Task<TResult>,catch到的异常会包装在属性里面,调用方法就可以从中获取异常信息,并选择正确的处理方式。
2、Task
你如果只是想知道执行的状态,而不需要一个具体的返回结果时,请使用Task。
与void对比呢,Task可以使用await进行等待新线程执行完毕。而void不需要等待。
3、Task<TResult>
当你添加async关键字后,需要返回一个将用于后续操作的对象,请使用Task<TResult>。
主要有两种方式获取结果值,一个是使用Result属性,一个是使用await。他们的区别在于:如果你使用的是Result,它带有阻塞性,即在任务完成之前进行访问读取它,当前处于活动状态的线程都会出现阻塞的情形,一直到结果值可用。所以,在绝大多数情况下,除非你有绝对的理由告诉自己,否则都应该使用await,而不是属性Result来读取结果值。
接下来我们来看个例子,在上一章的基础上我们添加异步的方法。
首先是仓储层接口:
using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Repository {/// <summary>/// 学生类仓储层接口/// </summary>public interface IStudentRepository{/// <summary>/// 根据学号获取学生信息/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>Student GetStuInfo(string stuNo);/// <summary>/// 根据学号获取学生信息(异步)/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>Task<Student> GetStuInfoAsync(string stuNo);} }
接着是仓储层实现:
using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Repository.Impl {/// <summary>/// 学生类仓储层/// </summary>public class StudentRepository : IStudentRepository{/// <summary>/// 根据学号获取学生信息/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>public Student GetStuInfo(string stuNo){//数据访问逻辑,此处为了演示就简单些var student = new Student();switch (stuNo){case "10000":student = new Student() { StuNo = "10000", Name = "张三", Sex = "男", Age = 20 };break;case "10001":student = new Student() { StuNo = "10001", Name = "钱七七", Sex = "女", Age = 18 };break;case "10002":student = new Student() { StuNo = "10002", Name = "李四", Sex = "男", Age = 21 };break;default:student = new Student() { StuNo = "10003", Name = "王五", Sex = "男", Age = 25 };break;}return student;}/// <summary>/// 根据学号获取学生信息(异步)/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>public virtual async Task<Student> GetStuInfoAsync(string stuNo){return await Task.Run(() => this.GetStuInfo(stuNo));}} }
然后是服务层接口:
using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks;using TianYa.DotNetShare.Model;namespace TianYa.DotNetShare.Service {/// <summary>/// 学生类服务层接口/// </summary>public interface IStudentService{/// <summary>/// 根据学号获取学生信息/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>Student GetStuInfo(string stuNo);/// <summary>/// 根据学号获取学生信息(异步)/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>Task<Student> GetStuInfoAsync(string stuNo);} }
再接着是服务层实现:
using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks;using TianYa.DotNetShare.Model; using TianYa.DotNetShare.Repository;namespace TianYa.DotNetShare.Service.Impl {/// <summary>/// 学生类服务层/// </summary>public class StudentService : IStudentService{/// <summary>/// 定义仓储层学生抽象类对象/// </summary>protected IStudentRepository StuRepository;/// <summary>/// 空构造函数/// </summary>public StudentService() { }/// <summary>/// 构造函数/// </summary>/// <param name="stuRepository">仓储层学生抽象类对象</param>public StudentService(IStudentRepository stuRepository){this.StuRepository = stuRepository;}/// <summary>/// 根据学号获取学生信息/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>public Student GetStuInfo(string stuNo){var stu = StuRepository.GetStuInfo(stuNo);return stu;}/// <summary>/// 根据学号获取学生信息(异步)/// </summary>/// <param name="stuNo">学号</param>/// <returns>学生信息</returns>public virtual async Task<Student> GetStuInfoAsync(string stuNo){return await StuRepository.GetStuInfoAsync(stuNo);}} }
最后进行控制器中的调用:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using TianYa.DotNetShare.CoreAutofacDemo.Models;using TianYa.DotNetShare.Service; using TianYa.DotNetShare.Repository; using TianYa.DotNetShare.Repository.Impl;namespace TianYa.DotNetShare.CoreAutofacDemo.Controllers {public class HomeController : Controller{/// <summary>/// 定义仓储层学生抽象类对象/// </summary>private IStudentRepository _stuRepository;/// <summary>/// 定义服务层学生抽象类对象/// </summary>private IStudentService _stuService;/// <summary>/// 定义服务层学生抽象类对象/// 属性注入:访问修饰符必须为public,否则会注入失败。/// </summary>public IStudentService StuService { get; set; }/// <summary>/// 定义仓储层学生实现类对象/// 属性注入:访问修饰符必须为public,否则会注入失败。/// </summary>public StudentRepository StuRepository { get; set; }/// <summary>/// 通过构造函数进行注入/// 注意:参数是抽象类,而非实现类,因为已经在Startup.cs中将实现类映射给了抽象类/// </summary>/// <param name="stuRepository">仓储层学生抽象类对象</param>/// <param name="stuService">服务层学生抽象类对象</param>public HomeController(IStudentRepository stuRepository, IStudentService stuService){this._stuRepository = stuRepository;this._stuService = stuService;}public IActionResult Index(){var stu1 = StuRepository.GetStuInfo("10000");var stu2 = StuService.GetStuInfo("10001");var stu3 = _stuService.GetStuInfo("10002");var stu4 = _stuRepository.GetStuInfo("1003");string msg = $"学号:10000,姓名:{stu1.Name},性别:{stu1.Sex},年龄:{stu1.Age}<br />";msg += $"学号:10001,姓名:{stu2.Name},性别:{stu2.Sex},年龄:{stu2.Age}<br/>";msg += $"学号:10002,姓名:{stu3.Name},性别:{stu3.Sex},年龄:{stu3.Age}<br/>";msg += $"学号:10003,姓名:{stu4.Name},性别:{stu4.Sex},年龄:{stu4.Age}<br/>";return Content(msg, "text/html", System.Text.Encoding.UTF8);}public async Task<IActionResult> Privacy(){var stu = await _stuService.GetStuInfoAsync("10000");return Json(stu);}[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]public IActionResult Error(){return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });}} }
至此完成处理,我们来访问一下/home/privacy,看看是否正常
可以看出是正常的
下面我们演示一下什么时候需要用到result属性:
//用了await则不需要Result属性 public async Task<IActionResult> Privacy() {var stu = await _stuService.GetStuInfoAsync("10000");return Json(stu); }
//没有用await则需要Result属性 public async Task<IActionResult> Privacy() {var stu = _stuService.GetStuInfoAsync("10000").Result;return Json(stu); }
至此我们的异步编程就讲解完了。
总结:
1、尽量优先使用Task<TResult>和Task作为异步方法的返回类型。
2、如果用了await则方法必须使用async来修饰,并且是Task的类型。
demo源码:
链接:https://pan.baidu.com/s/1Wb0Mebm-nh9YFOaYNLwO-g 提取码:1ayv
参考博文:https://www.cnblogs.com/fei686868/p/9637310.html
版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!
转载于:https://www.cnblogs.com/xyh9039/p/11391507.html
ASP.NET Core Web 应用程序系列(四)- ASP.NET Core 异步编程之async await相关推荐
- ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)...
在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...
- ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)...
在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...
- ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)...
在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...
- UkrGuru.SqlJson非常适合您的ASP.NET Core Web应用程序!
目录 背景 介绍 使用代码 服务设置 提供在页面中使用的DbService Index页 创建页面 编辑页面 详细信息页面 删除页面 在本技巧中,您将了解一种无需在ASP.NET Core Web应用 ...
- ASP.NET Core Web Razor Pages系列教程:使用ASP.NET Core创建Razor Pages Web应用程序
ASP .Net Core Razor Pages MySQL Tutorial 本系列教程翻译自微软官方教程,官方教程地址:Tutorial: Create a Razor Pages web ap ...
- ASP .NET Core Web Razor Pages系列教程四:使用数据库进行交互 entity-framework(MySQL/MariaDB 版)
系列文章目录:系列教程:使用ASP.NET Core创建Razor Pages Web应用程序 - zhangpeterx的博客 系列教程代码的GitHub地址:ASP .Net Core Razor ...
- ASP .NET Core Web Razor Pages系列教程四:使用数据库进行交互(SqlServer 版)
系列文章目录:系列教程:使用ASP.NET Core创建Razor Pages Web应用程序 - zhangpeterx的博客 上一个教程:ASP .NET Core 系列教程三:自动生成Razor ...
- ASP .NET Core Web Razor Pages系列教程五:更新Razor Pages页面
系列文章目录:系列教程:使用ASP.NET Core创建Razor Pages Web应用程序 - zhangpeterx的博客 系列教程代码的GitHub地址:ASP .Net Core Razor ...
- 基于.Net Core开发现代化Web应用程序系列课程和文章
这个系列课程是Anduin2017在B站上传的: 基于.Net Core开发现代化Web应用程序系列课程第1课之:课程简介 基于.Net Core开发现代化Web应用程序系列课程第2课之:.Net平台 ...
最新文章
- python函数手册68_直接在python中检索68个内置函数?
- Java 原生日志 java.util.logging
- python网络编程—TCP协议(一)
- 常用ARM指令总结(未完待续)
- 深入理解浏览器原理和架构|硬核
- python处理一亿条数据_Python基础数据处理库
- 怎么开通手机信息服务器,如何用手机建立网站
- React 第七章 条件渲染
- 确认!聚划算百亿补贴要向iPad 8等新品下手,这次是真的刚刚好
- 【shell】shell-grep -v 排除多个输出结果
- Serializing - 序列化 综述 – To be continued.
- Flex 中使用 FileReference 的 download 方法下载文件时的缓存刷新问题
- P1081 开车旅行
- 翻译python代码的软件_使用Python3中的gettext模块翻译Python源码以支持多语言
- html 酷狗音乐教程,仿酷狗html5手机音乐播放器主要部分代码_html5教程技巧
- 国外优秀JAVA技术网站推荐
- 如何查询论文和下载书籍
- crash工具分析sysdump使用
- Android返回桌面代码,安卓 双击返回键 返回桌面
- 微信小程序搜索,搜索历史,清除搜索历史,以及点击搜索历史实现搜索功能
热门文章
- linux内核关闭tcp校验,linux内核tcp调优规范与方案
- Knapsack Cryptosystem(2019牛客多校折半查询)
- 虚拟服务器 cms安装,轻量化云服务器怎么安装cms
- c语言的锁和Python锁,Python中全局解释器锁、多线程和多进程
- cygwin学习linux命令,cygwin 在windows下使用linux命令的方法
- activemq 延时队列以及不生效问题
- 3D点云论文汇总-实时更新
- 玩转GIT系列之【git切换到某个tag之后提示“detached HEAD】
- Mac OSX中memcached安装测试
- 使用OpenCV,Keras和Tensorflow构建Covid19掩模检测器