谈谈异步编程及在ASP.NE Core MVC中的使用
异步编程(Task)基本理解
Task类是.NET 4.0之后提供的异步操作抽象,需要导入System.Threading.Tasks命名空间。
Task类用于表示无返回值的异步操作,对于带有返回值的异步操作应使用Task类的子类Task<TResult>。
Task类和Task<TResult>类,后者是前者的泛型版本。TResult类型为Task所调用方法的返回值。
主要区别在于Task构造函数接受的参数是Action委托,而Task<TResult>接受的是Func<TResult>委托。
- Task(Action)
- Task<TResult>(Func<TResult>)
Task 异步编程的通俗理解
Task 异步编程模式是潮流,当然就是因为执行效率高。怎么理解异步编程,通俗讲就是“未来完成时”。带Task的表示他现在不一定有结果,等有结果了,他会通知你。当然实际上的意义就是,CPU现在可以忙别的,等有结果了再去处理你的。想想医院的医生看病就OK,他让你先做检查,先去化验,等你拿着化验结果到了,他再具体判定。在你去化验的同时医生也不会闲着,他用这段时间给后面病人诊断。理解了这个,技术上就能搞清楚了。简言之,就是“不空等结果,保存环境,等有结果了,恢复环境继续运行。同时他在等结果的同时去执行其他任务”。
异步就是不阻塞,不等 Task 方法执行完而是先去执行这个方法后边的代码。当写了 await 关键字的时候,就可以让 Task 执行完毕了才去执行它后边的代码。
Task类中的一些常用方法及应用
// 将参数中的异步操作在当前调度器中排队,并返回Task对象
(1)
public static Task Run(Action action);
(2)
public static Task<TResult> Run<TResult>(Func<TResult> function);
Task.Run方法是Task类中的静态方法,接受的参数是委托。返回值是为该Task对象。
Task.Run(Action)
Task.Run<TResult>(Func<Task<TResult>>)
(3)
public void Wait(); //等待当前Task任务完成
Task类创建的任务会加入线程池中。在实际开发中,更多情况下使用Task类的静态方法Run()或者工厂类TaskFactory的成员方法StartNew()来创建和启动新的任务(TaskFactory taskFactory = new TaskFactory();taskFactory.StartNew(Action);)。
虽然在异步方法中提示返回值可以为Task、Task<T>或者void,但是建议返回值选择Task或者Task<T>
例子1:创建控制台项目(.Net Core的)
static void Main(string[] args)
{
Task Task1 = new Task(() => Console.WriteLine("Task1"));
Task1.Start();
Console.ReadKey();
}
通过实例化一个Task对象,然后Start,这种方式中规中矩,但是实际应用中,通常采用更方便快捷的方式。
Task.Run(() => Console.WriteLine("异步编程"));这种方式直接运行了Task,不像上面的方法还需要调用Start();
默认情况下,Task任务是由线程池线程异步执行。要知道Task任务的是否完成,可以通过task.IsCompleted属性获得,也可以使用task.Wait来等待Task完成。Wait会阻塞当前线程。
例子2:
[code]static void Main(string[] args) { Task Task1 = Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("Foo"); Thread.Sleep(5000); }); Task1.Wait();//阻塞当前线程 ,等待上面任务完成再执行下面的代码 Console.WriteLine(Task1.IsCompleted); Console.WriteLine(Task1.IsCompleted); Console.WriteLine("ok"); Console.ReadKey(); }
运行结果:
对比一下:
[code]static void Main(string[] args) { Task Task1 = Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("Foo"); Thread.Sleep(5000); }); Console.WriteLine(Task1.IsCompleted); Task1.Wait();//阻塞当前线程,等待上面任务完成再执行下面的代码 Console.WriteLine(Task1.IsCompleted); Console.WriteLine("ok"); Console.ReadKey(); }
运行结果:
async/await 关键字
C# 5.0之后引入了async和await关键字,更好的支持并发操作。
async用于标记异步方法。async标记的方法返回值必须为Task、Task<TResult>、void其中之一。
await用于等待异步方法的结果。await关键字可以用在async方法和Task、Task<TResult>之前,用于等待异步任务执行结束。
如:await _resultRepository.ListAsync();
ASP.NET CORE MVC实例
下面采用一段MVC设计代码来说明一下Task类在MVC Designer中的如何使用
看下面这段代码,这里先定义一个接口,该接口定义异步操作
[code]public interface IAlbumService { //返回一个List<Album>的泛型列表 Task<List<Album>> GetAllAsync(); //返回一个Album model Task<Album> GetByIdAsync(int id); //返回一个Album model Task<Album> AddAsync(Album model); //无返回值的异步操作 Task UpdateAsync(Album model); //无返回值的异步操作 Task DeleteAsync(Album model); }
然后实现该接口:实现该接口中Task类
[code]public class AlbumEfService : IAlbumService { //声明一个只读字段,这里HeavyContext是一个数据库Model private readonly HeavyContext _context; //依赖注入该model public AlbumEfService(HeavyContext context) { _context = context; } public async Task<List<Album>> GetAllAsync() { return await _context.Albums.ToListAsync(); } public Task<Album> GetByIdAsync(int id) { return _context.Albums.FindAsync(id); } public async Task<Album> AddAsync(Album model) { _context.Albums.Add(model); await _context.SaveChangesAsync(); return model; } public async Task UpdateAsync(Album model) { _context.Entry(model).State = EntityState.Modified; await _context.SaveChangesAsync(); } public async Task DeleteAsync(Album model) { _context.Albums.Remove(model); await _context.SaveChangesAsync(); } }
在Controller中注入该接口服务
[code][Authorize] public class AlbumController : Controller { private readonly IAlbumService _albumService; public AlbumController(IAlbumService albumService) { _albumService = albumService; } // GET: Album public async Task<ActionResult> Index() { var albums = await _albumService.GetAllAsync(); return View(albums); } // GET: Album/Details/5 public async Task<ActionResult> Details(int id) { var album = await _albumService.GetByIdAsync(id); if (album == null) { return RedirectToAction(nameof(Index)); } return View(album); } // GET: Album/Create public ActionResult Create() { var newModel = new AlbumCreateViewModel(); return View(newModel); } ......
在Startup中注入操作Album model所需要的服务
[code] services.AddScoped<IAlbumService, AlbumEfService>();
提问:服务注入的方式还有哪两种:
(1)最常用的注入方式,以接口形式暴露服务
services.AddScoped( typeof(IUserService), typeof(UserService));
services.AddScoped<IUserService, UserService>();
(2)自己注入自己,以实现形式暴露服务
services.AddScoped< UserService>();
services.AddScoped( typeof( UserService));
- 点赞
- 收藏
- 分享
- 文章举报
- Asp.net Core MVC在Ubuntu部署,并且使用nginx反向代理
- 如何使用Rotativa在ASP.NET Core MVC中创建PDF详解
- 使用Rotativa在ASP.NET Core MVC中创建PDF
- 3分钟快速学会在ASP.NET Core MVC中如何使用Cookie
- ASP.Net Core 2.2 MVC入门到基本使用系列 (五)
- asp.net core 使用 Areas 组织 MVC 项目
- ASP.NET Core中使用默认MVC路由的配置
- ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下
- ASP.NET Core开发-MVC 使用dotnet 命令创建Controller和View
- 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射
- ASP.Net Core 2.2 MVC入门到基本使用系列 (三)
- ASP.Net Core 2.2 MVC入门到基本使用系列 (四)
- 使用ASP.NET Core MVC应用程序中的ResponseCache属性处理缓存(转载)
- ASP.Net Core 2.2 MVC入门到基本使用系列 (二)
- ASP.NET Core 中文文档 第四章 MVC(3.4)如何使用表单
- AspNetCoreMvc使用MongoDB,快来get一下吧。
- Asp.net Mvc Framework可以在Controller中使用的Url.Action方法
- 跟ASP.NET MVC一起使用jQuery
- 在ASP.Net MVC框架下使用富文本编辑器(FCKEditor,更新至:v1.0.1)(2010-05-22:已加上源代码)
- 在 ASP.NET MVC 项目中使用 WebForm