hello,又见面啦,昨天我们简单的介绍了如何去创建和运行一个task、如何实现task的同步执行、如何阻塞等待task集合的执行完毕等待,昨天讲的是task的最基本的知识点,如果你没有看昨天的博客,也不要急,你可以点击下面的地址, 聊聊多线程哪一些事儿(task)之 一),先看看后,在回到这儿来继续交流学习今天的文章,谢谢!

今天主要和大家交流分享的是:task的延续操作、task的异步取消、异步方法等知识点,希望通过本篇文章,能够给你带来一点点帮助我就高兴的不要不要的啦。当然啦,既然是交流,如果我有什么说的不对,或者说的不好的地方,大家多多指点,多多包涵,如果能够得到大牛的指点,我也会高兴的合不拢嘴,谢谢。好了,不废话了,言归正传,继续今天的分享加交流。

Task延续操作之WhenAny、WhenAll、ContinueWith

上一篇文章我们已经知道可以通过task.wait/task.WaitAny/task.WaitAll,等方法来实现等待一个tsak或者一组task的执行完毕,这一个方法都会阻塞主线程(如果没有看一篇文章的请单击查看:聊聊多线程哪一些事儿(task)之 一),也就是这一些操作都是主流程的一个必然环节,但是我们在实际项目中,也还会遇到这样的场景,那就是主流程根本不关心task的执行结果,但是task执行完毕后,需要执行一个其他的子业务,那么这个时候WhenAny、WhenAll、ContinueWith就派上用场了,这几个方法也就专门是为这样的场景而存在的。哈哈,说了这么多,是不是觉得有点抽象,有点云里雾里的感觉,说实话,我自己都觉得说的太空洞,还不如来一个实际的场景+代码实例,这样整的更明白。

实际业务场景:我想了半天,到得用什么样的业务场景比较合适呢,最终决定还是以昨天酒店客房数据查询为例进行为例。用户在线预订酒店时,由于真正的客房预订是需要实时的到第三接口平台预订,所以用户在自己系统下单后,并不代表真正的酒店预订成功,真正的酒店预订成功,是需要通过接口到第三方系统下单成功才算真正的预订成功,并且一个平台对接的接口都会有多个,平台最终会比价后,选择一个平台利用最大化的接口下单。这样以来,系统不可能让用户等待到第三方接口下单成功后,在返回的用户吧,这样用户是没有那么好的心情的来等待的,并且这样也很容易超时的,所以在实际项目处理上,是需要将本系统下单和第三接口预订两个步骤解耦,实现异步预订,其大致的业务逻辑是这样的。

第一步:用户在系统发起酒店预订请求

第二步:本系统下单成功,并返回给用户

第三步:开启一个异步线程,到接口方下单

异步线程的处理逻辑大概是:

其一:具有该客房的接口方各开启一个异步线程

其二:每一个线程的具体逻辑是,根据客房信息查询具体的客房信息(客房状态、价格、服务等)

其三:当每一个异步线程都执行完毕后,对获取到接口数据进行对比分析,选择一个最优的接口方进行预订

其四:预订成功后,并发送一个消息给客户

好了,下面用一个简单的实例代码来模拟上面的处理逻辑和流程

/// <summary>
/// 酒店在线预订操作
/// </summary>
/// <param name="hotelBookInfo">用户预订的酒店信息</param>
/// <returns>预订结果</returns>
private static object HotelBook(object hotelBookInfo)
{
Console.WriteLine("用户发起了酒店预订请求!");
Console.WriteLine(""); // 第一步:首先本系统落地酒店预订相关操作(数据校验、数据落地、日志记录等等)
// ---此处省略具体的业务逻辑代码,根据业务需要自由发挥 // 第二步:根据具有该客房的酒店接口商,开启异步线程预订酒店
//(假设第一步操作都成功的,并且 携程和艺龙都有该客房) // 模拟存储获取到的酒店客房数据集合
List<string> listHotelRoomInfro = new List<string>(); // 其一、通过传统的 new 方式来实例化一个task对象,获取 携程 的客房时时数据
Task newCtripTask = new Task(() =>
{
// 具体获取业务逻辑处理...
Thread.Sleep(new Random().Next(, ));
Console.WriteLine("携程 接口数据获取完毕!");
Console.WriteLine("");
listHotelRoomInfro.Add("我是来自 携程 的最新客房信息,该客房可预订,预订价格为:100元");
}); // 启动 tsak
newCtripTask.Start(); // 其二、通过工厂 factory 来生成一个task对象,并自启动:获取 艺龙 的客房数据
Task factoryElongTask = Task.Factory.StartNew(() =>
{
// 具体获取业务逻辑处理...
Thread.Sleep(new Random().Next(, ));
Console.WriteLine("艺龙 接口数据获取完毕!");
Console.WriteLine("");
listHotelRoomInfro.Add("我是来自 艺龙 的最新客房信息,该客房可预订,预订价格为:99元");
}); // 其三:通过 Task.WhenAll() 来执行 携程和艺龙的客房数据获取结果的后续处理
// Task.WhenAll() 可以用 Task.Factory.ContinueWhenAll()来代替,两种的效果是一样的
Task.Factory.ContinueWhenAll(new Task[] { newCtripTask, factoryElongTask }, (t) => { });
Task.WhenAll(newCtripTask, factoryElongTask).ContinueWith((t) =>
{
Console.WriteLine("所有接口数据获取完毕,现在进行最优选择!");
Console.WriteLine("");
// 对比 所有接口获取的实时数据,找到一个平台利益最大化的接口预订
// 具体的规则,每个平台都有自己的规则,在此我们简单的以价格最低为准,具体的对比逻辑就不在写了
// 根据数据分析,最终艺龙的价格最低,所以直接预订艺龙的数据 Console.WriteLine("艺龙接口最优,现在调用艺龙在线预订接口!");
Console.WriteLine("");
// 模拟调用艺龙的酒店预订接口,进行酒店预订
Thread.Sleep(new Random().Next(, ));
// 预订成功后,系统数据落地的相关业务操作.....
Console.WriteLine("艺龙在线预订成功,开始后续业务流程处理!");
}); // 第三步步:返回用户,下单成功
Console.WriteLine("您好,你的酒店下单成功,具体的预订结果等待第三方酒店提高商的返回结果为准!谢谢");
Console.WriteLine(""); return "构建下单成功相关信息";
}
 

执行结果:

通过上面的执行结果,我们可以得出以下几点:

其一、WhenAll里面的逻辑是在所有tsak都执行完毕后,在执行

其二、whenAll的执行,不会影响主线程的执行

其三、其实简单的理解,WhenAll可以理解为一个task组的异步回调

好了,详细的举例说了whenAll的使用,至于 WhenAny 使用就不在详细说明了,其实从字面意思都能够看明白啦,就是只要所有的task集合中,只有有一个task执行完成,就在执行whenAny里面的逻辑,也就是说,wenAll和whenAny的唯一区别就是:前者是要所有task都执行完毕才执行,后者只需要有一个执行完毕就执行里面的逻辑。

其实WhenAny 的有实际应用场景也是很多的,比如,一个具有竞争的业务逻辑中,最终只选择一个效率对快的一个,那么WhenAny就能够发挥其作用了。

Task.WhenAll与Task.Factory.ContinueWhenAll

Task.WhenAny 与Task.Factory.ContinueWhenAny

这两者是一个成对的等效操作,其实你阅读两个的底层源码实现,你会发现,其实最终第底层实现都是调用的TaskFactory中的同一方法实现,所以就不在啰嗦的写一次Task.Factory.ContinueWhenAll的场景应用,需要阅读的底层源码的,可以查看下面地址进行阅读:https://blog.csdn.net/weixin_33701294/article/details/85958795

好了,今天就写到这儿了,我仔细看了一下,文章篇幅已经够多了,本篇文章就不在介绍 task的异步取消、异步方法这两个知识点了,明天我会在单独一篇文章专门来介绍这两个知识点,想继续看明天的后续文章的小伙伴们,点关注哦,明天一定补上,谢谢!

猜您喜欢:

 第一篇:聊聊多线程哪一些事儿(task)之 一创建运行与阻塞

 第二篇:聊聊多线程哪一些事儿(task)之 二 延续操作

 第三篇:聊聊多线程那一些事儿(task)之 三 异步取消和异步方法

 第四篇:聊聊多线程那一些事儿 之 四 经典应用(取与舍、动态创建)

END
为了更高的交流,欢迎大家关注我的公众号,扫描下面二维码即可关注,谢谢:

聊聊多线程哪一些事儿(task)之 二 延续操作的更多相关文章

  1. 聊聊多线程哪一些事儿(task)之 一

    多线程,一个多么熟悉的词汇,作为一名程序员,我相信无论是从事什么开发语言,都能够轻轻松松说出几种实现多线程的方式,并且在实际工作种也一定用到过多线程,比如:定时器.异步作业等等,如果你说你没有用过多线 ...

  2. 聊聊多线程那一些事儿(task)之 三 异步取消和异步方法

    hello,咋们又见面啦,通过前面两篇文章的介绍,对task的创建.运行.阻塞.同步.延续操作等都有了很好的认识和使用,结合实际的场景介绍,这样一来在实际的工作中也能够解决很大一部分的关于多线程的业务 ...

  3. 聊聊多线程哪一些事儿(task)之 三 异步取消和异步方法

    hello,咋们又见面啦,通过前面两篇文章的介绍,对task的创建.运行.阻塞.同步.延续操作等都有了很好的认识和使用,结合实际的场景介绍,这样一来在实际的工作中也能够解决很大一部分的关于多线程的业务 ...

  4. 聊聊多线程那一些事儿 之 五 async.await深度剖析

     hello task,咱们又见面啦!!是不是觉得很熟读的开场白,哈哈你哟这感觉那就对了,说明你已经阅读过了我总结的前面4篇关于task的文章,谢谢支持!感觉不熟悉的也没有关系,在文章末尾我会列出前四 ...

  5. 聊聊RabbitMQ那一些事儿之一基础应用

    聊聊RabbitMQ那一些事儿之一基础应用 Hi,各位热爱技术的小伙伴您们好,今年的疫情害人啊,真心祝愿您和您的家人大家都平平安安,健健康康.年前到现在一直没有总结点东西,写点东西,不然久了自己感觉自 ...

  6. 一个轻巧高效的多线程c++stream风格异步日志(二)

    目录 一个轻巧高效的多线程c++stream风格异步日志(二) 前言 LogFile类 AsyncLogging类 AsyncLogging实现 增加备用缓存 结语 一个轻巧高效的多线程c++stre ...

  7. 2 Task中的延续和7种阻塞

    1.wait using System; using System.Threading; using System.Threading.Tasks; namespace 多线程_List { clas ...

  8. Thinkphp入门 二 —空操作、空模块、模块分组、前置操作、后置操作、跨模块调用(46)

    原文:Thinkphp入门 二 -空操作.空模块.模块分组.前置操作.后置操作.跨模块调用(46) [空操作处理] 看下列图: 实际情况:我们的User控制器没有hello()这个方法 一个对象去访问 ...

  9. windows下mongodb基础玩法系列二CURD操作(创建、更新、读取和删除)

    windows下mongodb基础玩法系列 windows下mongodb基础玩法系列一介绍与安装 windows下mongodb基础玩法系列二CURD操作(创建.更新.读取和删除) windows下 ...

随机推荐

  1. 微信小程序记录

    1.vs code 可以安装 Vetur-wepy 对代码高亮的提示. 2.取消swiper组件的手动滑动效果 在 swiper-item 中添加 catchtouchmove='catchTouch ...

  2. UVa 10323 【数学】

    UVa 10323 题目:计算阶乘在10000~6227020800之间的值,不在范围对应输出Under或者Over. 分析:简单题.数论.因为13!=6227020800,7!<10000&l ...

  3. mysql LIMIT 子句用法及原理

    使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,已 经为我们提供了这样一个功能. LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数.LIMIT 接 ...

  4. Java练习 SDUT-1689_斐波那契?

    斐波那契? Time Limit: 1000 ms Memory Limit: 32768 KiB Problem Description 给出一个数列的递推公式,希望你能计算出该数列的第N个数.递推 ...

  5. Mac OSX原生读写NTFS功能开启方法

    macOX系统内建的NTFS支持默认只能读不能写 原生读写NTFS,需要自行终端命令手动开启 1. 插上磁盘 此时Mac桌面应该会显示出插入的磁盘,但是当你想把文件拖入磁盘的时候,发现是不能拖进去的, ...

  6. 前端知识---html

    HTML HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可以让浏 ...

  7. AtCoder Regular Contest 058

    这个应该是第一场有英文的atcoder吧??不过题解却没有英文的... 从前往后慢慢做... C こだわり者いろはちゃん / Iroha's Obsession 数据范围这么小,直接暴力 #inclu ...

  8. 对装饰器@wraps的解释(一看就懂)-- 并对装饰器详解

    1. 先看一段代码 def is_login(func): def foo(*args,**kwargs): return func(*args,**kwargs) return foo def te ...

  9. oracle 用表连接替换EXISTS

    通常来说 , 采用表连接的方式比EXISTS更有效率 SELECT ENAME FROM EMP E WHERE EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT_NO ...

  10. 【codeforces 777E】Hanoi Factory

    [题目链接]:http://codeforces.com/problemset/problem/777/E [题意] 让你摆汉诺塔片; 要求在上面的片的外圈大于在下面的片的内圈,且小于下面的片的外圈; ...