前言

    在上一章 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(补充)的更多相关文章

  1. WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)

    WebAPI调用笔记   前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...

  2. Asp.Net Core 轻松学-多线程之Task快速上手

    前言     Task是从 .NET Framework 4 开始引入的一项基于队列的异步任务(TAP)模式,从 .NET Framework 4.5 开始,任何使用 async/await 进行修饰 ...

  3. Asp.Net Core 轻松学系列-1阅读指引目录

    https://www.cnblogs.com/viter/p/10474091.html 目录 前言 1. 从安装到配置 2. 业务实现 3. 日志 4. 测试 5. 缓存使用 6.网络和通讯 7. ...

  4. Asp.Net Core 轻松学-使用MariaDB/MySql/PostgreSQL和支持多个上下文对象

    前言 在上一篇文章中(Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库)[https://www.cnblogs.com/viter/p/10243577.html],介 ...

  5. Asp.Net Core 轻松学-利用文件监视进行快速测试开发

    前言     在进行 Asp.Net Core 应用程序开发过程中,通常的做法是先把业务代码开发完成,然后建立单元测试,最后进入本地系统集成测试:在这个过程中,程序员的大部分时间几乎都花费在开发.运行 ...

  6. 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange

    如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...

  7. C# 中一些类关系的判定方法 C#中关于增强类功能的几种方式 Asp.Net Core 轻松学-多线程之取消令牌

    1.  IsAssignableFrom实例方法 判断一个类或者接口是否继承自另一个指定的类或者接口. public interface IAnimal { } public interface ID ...

  8. Asp.Net Core 轻松学-一行代码搞定文件上传 JSONHelper

    Asp.Net Core 轻松学-一行代码搞定文件上传   前言     在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能:通过创建 ...

  9. Asp.Net Core 轻松学系列-5利用 Swagger 自动生成接口文档

    目录 前言 结语 源码下载 前言     目前市场上主流的开发模式,几乎清一色的前后端分离方式,作为服务端开发人员,我们有义务提供给各个客户端良好的开发文档,以方便对接,减少沟通时间,提高开发效率:对 ...

随机推荐

  1. Python_正则表达式样例

    ''' 正则表达式是字符串处理的有力工具和技术,正则表达式使用预定义的特定模式去匹配一类具有共同特征的字符串, 主要用于字符串处理,可以快速.准确地完成复杂的查找.替换等处理要求. 正则表达式由元字符 ...

  2. python_特殊函数

    __new__() 类的静态方法,用于确定是否要创建对象__init__() 构造函数,生成对象时调用__del__() 析构函数,释放对象时调用__add__() +__sub__() -__mul ...

  3. C语言 > 构造素数表

    #include <stdio.h> #define NUMBER 1000 int main(){ int isPrime[NUMBER]; ; i < NUMBER; i++){ ...

  4. css基础--深入理解弹性盒flex布局

    欢迎访问我的个人博客:http://www.xiaolongwu.cn 1. 前言 flex弹性盒,是一种布局方式,当页面需要适应不同的屏幕大小以及设备类型时,它依然能确保元素 拥有更恰当的排布行为, ...

  5. 树莓派+花生棒+leanote搭建自己的笔记服务器

    背景 对于一个程序猿来说.女朋友可以(暂时)没有,但是不能没有一个很好的记笔记的应用.因为记笔记可以帮助自己积累学习提升自己.每一次回头看自己记得笔记,你都会有新的理解. 也许有人会说,用有道云啊,有 ...

  6. 怎么确定Oracle客户端安装成功

    可通过能否登录sqlplus来判断是否安装成功. 操作系统:windows10 oracle版本:oracle 11g 步骤: 1.电脑win键+R键,输入cmd,进入命令提示符. 2.命令行中输入: ...

  7. http://www.runoob.com/lua/lua-basic-syntax.html

    Lua优点及特性 Lua 是一个小巧的脚本语言. 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能.Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行.Lua并没 ...

  8. Linux kernel的中断子系统之(五):驱动申请中断API

    返回目录:<ARM-Linux中断系统>. 总结:二重点区分了抢占式内核和非抢占式内核的区别:抢占式内核可以在内核空间进行抢占,通过对中断处理进行线程化可以提高Linux内核实时性. 三介 ...

  9. Ambiguous mapping found

    If you have a single default method (without explicit path mapping), then all requests without a mor ...

  10. 全国省市县区域信息最新数据库脚本(mysql版本)

    /*Navicat MySQL Data Transfer Source Server : localhostSource Server Version : 50717Source Host : lo ...