Asp.Net Core 轻松学-多线程之Task(补充)
前言
在上一章 Asp.Net Core 轻松学-多线程之Task快速上手 文章中,介绍了使用Task的各种常用场景,但是感觉有部分内容还没有完善,在这里补充一下。
1. 任务的等待
在使用 Task 进行基于队列的异步任务(TAP)的时候,对于刚入门的同学来说,只是简单的了解了使用 Task 可以在后台处理异步任务,但是对于阻塞调用可能还有有一些不太明白,异步任务默认是不阻塞的执行过程,当一个 Task 被创建出来的时候,并没有被压入队列中,而是开始执行的时候,才会进入队列中;执行一个异步任务可以设置等待
1.1 使用 await 进行等待任务完成
[HttpGet]
public async Task<string> Get()
{
string result = string.Empty;
await Task.Run(() =>
{
result = "Hello World!";
});
return result;
}
上面的异步方法 Get() 内部执行了一个 Task,为了保持方法在返回的时候能够给变量 result 设置值,这里使用了 await 等待任务完成,在任务未完成前,即 result 未被设置值 Hello World! 前,该接口将一直阻塞,直到任务完成。
1.1 使用 Wait()
[HttpGet("WaitTest")]
public string WaitTest(int id)
{
string result = string.Empty;
var waitTask = Task.Run(() =>
{
result = "Hello World!";
});
waitTask.Wait(TimeSpan.FromSeconds(5));
return result;
}
上面的代码定义了一个 TAP ,waitTask 使用了 Wait() 方法进行等待并传入一个时间,表示等待 5 秒中后退出阻塞过程,
1.2 使用 CancellationToken 方法
[HttpGet("WaitToken")]
public string WaitToken(int id)
{
var result = string.Empty;
CancellationTokenSource cts = new CancellationTokenSource();
var taskToken = Task.Run(() =>
{
cts.CancelAfter(TimeSpan.FromSeconds(1));
Task.Delay(2000).Wait();
result = "Hello World!";
});
taskToken.Wait(cts.Token);
return result;
}
上面的任务 taskToken ,则使用了取消令牌,当令牌没有收到取消通知的时候,该任务将一直等待, taskToken 任务内部指示取消令牌 1 秒后取消,同时,任务内部使用 Task.Delay 阻塞 2 秒,这很特别,这种设置使得 taskToken 任务将引发任务取消的异常而导致无法给 result 变量进行值设置,如果你对取消令牌不太了解,建议阅读我之前的文章 Asp.Net Core 轻松学-多线程之取消令牌
2. 同步方法中的异步任务
在同步方法中,我们可以非常容易的创建一个 Task 任务,特别是 .Net Core 提供了 Task 这么方便的使用方式的情况下,在某些场景下,就会出现一些意想不到的问题,我的忠告是:在使用 TAP 的时候,尽可能的使用可等待的任务,特别是需要注意不要在 TAP 中运行一些耗时较长的任务,比如批量处理数据、事务过程等等,如果真的是需要有这一类型的任务需要使用 Task 进行处理,那么我的建议是,将这些任务缩小,然后尽快的结束,比如,你可以使用消息队列来执行批量处理数据,而 Task 的任务则缩小至把处理条件丢到消息队列中,这样的解耦才是正确的选择,长时间运行于后台的 TAP,常常导致许多问题,比如消息冒泡、服务重启,都有可能会中断 TAP 线程,要知道,所有的 TAP 都是后台线程,当主进程退出的时候,后台线程也将被清理
3. 手动排队任务
在 TheadPool 内部,提供了一个排队的方法,当线程池资源可用后,将会自动的执行该队列,这样做的好处显而易见,就是你可以通过定义一系列的任务,然后等待线程池去按顺序处理它,这个排队的过程本质上就是队列
3.1 手动排队任务
[HttpGet("TaskQueue")]
public bool TaskQueue()
{
var inQueues = ThreadPool.QueueUserWorkItem(ThreadProc);
return inQueues;
}
private void ThreadProc(Object stateInfo)
{
Console.WriteLine("此任务来自线程池队列执行");
}
上面的代码中,在 TaskQueue() 内部使用 ThreadPool.QueueUserWorkItem() 将方法 ThreadProc(Object stateInfo) 压入队列中,并返回一个值:inQueues ,该值指示任务压入队列是否成功,在 .Net Core 中,ThreadPool.QueueUserWorkItem() 提供了 3 个方法重载,可以按需使用;使用重载方法,甚至可以在压入任务的时候传入参数调用,类似下面的代码
3.2 在排队任务时传递参数
[HttpGet("TaskQueue")]
public bool TaskQueue()
{
var inQueues = ThreadPool.QueueUserWorkItem(ThreadProc);
var inQueuesSecond = ThreadPool.QueueUserWorkItem(ThreadProc, "这是一条测试消息");
return inQueues;
}
private void ThreadProc(Object stateInfo)
{
Console.WriteLine(stateInfo);
}
如果业务需要,该参数还可传入实体对象
4. 混合方法(Hybrid Approach)
使用混合方法执行 TAP 的好处是,可以隐藏业务实现细节,提供统一调用入口
4.1 定义混合方法
[HttpGet("HyBrid")]
public Task<string> HyBrid([FromQuery]string value)
{
return HyBridInternal(value);
}
private async Task<string> HyBridInternal(string value)
{
await Task.Run(() =>
{
Console.WriteLine(value);
});
return "Your Input:" + value;
}
混合方法,不要被它的名头唬住,你可以把它看成一个方法重载,这样做的好处是,当发生异常是,你可以快速的定位到出现异常的方法,而不是任务
结束语
本文的内容只是上一篇文章的补充,所以这里就不在放入执行结果,但是示例代码还是一样的奉上
示例代码下载
https://github.com/lianggx/EasyAspNetCoreDemo/tree/master/Ron.TaskSecond
Asp.Net Core 轻松学-多线程之Task(补充)的更多相关文章
- WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)
WebAPI调用笔记 前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...
- Asp.Net Core 轻松学-多线程之Task快速上手
前言 Task是从 .NET Framework 4 开始引入的一项基于队列的异步任务(TAP)模式,从 .NET Framework 4.5 开始,任何使用 async/await 进行修饰 ...
- Asp.Net Core 轻松学系列-1阅读指引目录
https://www.cnblogs.com/viter/p/10474091.html 目录 前言 1. 从安装到配置 2. 业务实现 3. 日志 4. 测试 5. 缓存使用 6.网络和通讯 7. ...
- Asp.Net Core 轻松学-使用MariaDB/MySql/PostgreSQL和支持多个上下文对象
前言 在上一篇文章中(Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库)[https://www.cnblogs.com/viter/p/10243577.html],介 ...
- Asp.Net Core 轻松学-利用文件监视进行快速测试开发
前言 在进行 Asp.Net Core 应用程序开发过程中,通常的做法是先把业务代码开发完成,然后建立单元测试,最后进入本地系统集成测试:在这个过程中,程序员的大部分时间几乎都花费在开发.运行 ...
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...
- C# 中一些类关系的判定方法 C#中关于增强类功能的几种方式 Asp.Net Core 轻松学-多线程之取消令牌
1. IsAssignableFrom实例方法 判断一个类或者接口是否继承自另一个指定的类或者接口. public interface IAnimal { } public interface ID ...
- Asp.Net Core 轻松学-一行代码搞定文件上传 JSONHelper
Asp.Net Core 轻松学-一行代码搞定文件上传 前言 在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能:通过创建 ...
- Asp.Net Core 轻松学系列-5利用 Swagger 自动生成接口文档
目录 前言 结语 源码下载 前言 目前市场上主流的开发模式,几乎清一色的前后端分离方式,作为服务端开发人员,我们有义务提供给各个客户端良好的开发文档,以方便对接,减少沟通时间,提高开发效率:对 ...
随机推荐
- 初入thinkphp
花3天时间入门了php和thinkphp框架,紧接着就做了一个小后台,简单使用了thinkphp框架封装的一些类和函数. 现在来总结一下: //登陆函数 public func ...
- JS的事件绑定、事件流模型
.t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.JS事件 (一)JS事件分类 1.鼠标事件:click/dbclick ...
- webpack4:连奏中的进化
webpack4在2月底的时候发布,这次webpack4有了一个名字"Legato",也就是"连奏"的意思,寓意webpack在不断进化,而且是无缝(no-ga ...
- JaveScript基础(3)之正则表达式
1.创建正则表达式的两张方法: A.var reg=/pattern/; 注意:斜杠内不能加单引号或双引号 B.vae reg=new RegExp('pattern'); 注意:括号内要用单引号括 ...
- Bash特殊变量:$0, $#, $*, $@, $?, $$实战
在linux下配置shell参数说明 前面已经讲到,变量名只能包含数字.字母和下划线,因为某些包含其他字符的变量有特殊含义,这样的变量被称为特殊变量. 例如,$ 表示当前Shell进程的ID,即pid ...
- spring-security doc logout
18.5.3 Logging Out Adding CSRF will update the LogoutFilter to only use HTTP POST. This ensures that ...
- EF生成模型出现异常:表“TableDetails“中列“IsPrimaryKey”的值为DBNull解决方法
Entity Framework连接MySQL时:由于出现以下异常,无法生成模型:"表"TableDetails"中列"IsPrimaryKey"的值 ...
- 1. Java面向对象之泛型-认识泛型
package generic; class Point{ private Object x; private Object y; public Object getX() { return x; ...
- python基础autopep8__python代码规范
关于PEP 8 PEP 8,Style Guide for Python Code,是Python官方推出编码约定,主要是为了保证 Python 编码的风格一致,提高代码的可读性. 官网地址:http ...
- python assert的作用
使用assert断言是学习python一个非常好的习惯,python assert 断言句语格式及用法很简单.在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件 ...