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相关推荐

  1. ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)...

    在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...

  2. ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)...

    在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...

  3. ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)...

    在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...

  4. UkrGuru.SqlJson非常适合您的ASP.NET Core Web应用程序!

    目录 背景 介绍 使用代码 服务设置 提供在页面中使用的DbService Index页 创建页面 编辑页面 详细信息页面 删除页面 在本技巧中,您将了解一种无需在ASP.NET Core Web应用 ...

  5. 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 ...

  6. ASP .NET Core Web Razor Pages系列教程四:使用数据库进行交互 entity-framework(MySQL/MariaDB 版)

    系列文章目录:系列教程:使用ASP.NET Core创建Razor Pages Web应用程序 - zhangpeterx的博客 系列教程代码的GitHub地址:ASP .Net Core Razor ...

  7. ASP .NET Core Web Razor Pages系列教程四:使用数据库进行交互(SqlServer 版)

    系列文章目录:系列教程:使用ASP.NET Core创建Razor Pages Web应用程序 - zhangpeterx的博客 上一个教程:ASP .NET Core 系列教程三:自动生成Razor ...

  8. ASP .NET Core Web Razor Pages系列教程五:更新Razor Pages页面

    系列文章目录:系列教程:使用ASP.NET Core创建Razor Pages Web应用程序 - zhangpeterx的博客 系列教程代码的GitHub地址:ASP .Net Core Razor ...

  9. 基于.Net Core开发现代化Web应用程序系列课程和文章

    这个系列课程是Anduin2017在B站上传的: 基于.Net Core开发现代化Web应用程序系列课程第1课之:课程简介 基于.Net Core开发现代化Web应用程序系列课程第2课之:.Net平台 ...

最新文章

  1. python函数手册68_直接在python中检索68个内置函数?
  2. Java 原生日志 java.util.logging
  3. python网络编程—TCP协议(一)
  4. 常用ARM指令总结(未完待续)
  5. 深入理解浏览器原理和架构|硬核
  6. python处理一亿条数据_Python基础数据处理库
  7. 怎么开通手机信息服务器,如何用手机建立网站
  8. React 第七章 条件渲染
  9. 确认!聚划算百亿补贴要向iPad 8等新品下手,这次是真的刚刚好
  10. 【shell】shell-grep -v 排除多个输出结果
  11. Serializing - 序列化 综述 – To be continued.
  12. Flex 中使用 FileReference 的 download 方法下载文件时的缓存刷新问题
  13. P1081 开车旅行
  14. 翻译python代码的软件_使用Python3中的gettext模块翻译Python源码以支持多语言
  15. html 酷狗音乐教程,仿酷狗html5手机音乐播放器主要部分代码_html5教程技巧
  16. 国外优秀JAVA技术网站推荐
  17. 如何查询论文和下载书籍
  18. crash工具分析sysdump使用
  19. Android返回桌面代码,安卓 双击返回键 返回桌面
  20. 微信小程序搜索,搜索历史,清除搜索历史,以及点击搜索历史实现搜索功能

热门文章

  1. linux内核关闭tcp校验,linux内核tcp调优规范与方案
  2. Knapsack Cryptosystem(2019牛客多校折半查询)
  3. 虚拟服务器 cms安装,轻量化云服务器怎么安装cms
  4. c语言的锁和Python锁,Python中全局解释器锁、多线程和多进程
  5. cygwin学习linux命令,cygwin 在windows下使用linux命令的方法
  6. activemq 延时队列以及不生效问题
  7. 3D点云论文汇总-实时更新
  8. 玩转GIT系列之【git切换到某个tag之后提示“detached HEAD】
  9. Mac OSX中memcached安装测试
  10. 使用OpenCV,Keras和Tensorflow构建Covid19掩模检测器