终于明白了 C# 中 Task.Yield 的用途
最近在阅读 .NET Threadpool starvation, and how queuing makes it worse 这篇博文时发现文中代码中的一种 Task 用法之前从未见过,在网上看了一些资料后也是云里雾里不知其解,很是困扰。今天在程序员节的大好日子里终于想通了,于是写下这篇随笔分享给大家,也过过专心写博客的瘾。
这种从未见过的用法就是下面代码中的 await Task.Yield()
:
static async Task Process(){ await Task.Yield(); var tcs = new TaskCompletionSource<bool>();Task.Run(() =>{Thread.Sleep(1000);tcs.SetResult(true);});tcs.Task.Wait();
}
(注:上面的代码不是示例,只是因为这段代码而初遇 await Task.Yield)
Task.Yield 简单来说就是创建时就已经完成的 Task ,或者说执行时间为0的 Task ,或者说是空任务,也就是在创建时就将 Task 的 IsCompeted 值设置为0。
那 await 一个空任务会怎样?我们知道在 await 时会释放当前线程,等所 await 的 Task 完成时会从线程池中申请新的线程继续执行 await 之后的代码,这本来是为了解决异步操作(比如IO操作)霸占线程实际却用不到线程的问题,而 Task.Yield 却产生了一个不仅没有异步操作而且什么也不干的 Task ,不是吃饱了撑着吗?
今天吃晚饭的时候终于想明白了——吃饱了没有撑。Task.Yield 产生的空任务仅仅是为 await 做嫁衣,而真正的图谋是借助 await 实现线程的切换,让 await 之后的操作重新排队从线程池中申请线程继续执行。这样做有什么好处呢?线程是非常非常宝贵的资源,千金难买一线程,而且有优先级,提高线程利用率的重要手段之一就是及时将线程分配给最需要的地方,而最奢侈的之一是让一个优先级低执行时间长的操作一直占用着一个线程,await Task.Yield 可以让你巧妙地借助 await 的线程切换能力,将不太重要的比较耗时的操作放在新的线程(重新排队从线程池中申请到的线程)中执行。打个比方,很多人排队在外婆家就餐,你来的时候比较巧,正好有位置,但你本来就不着急肚子也不太饿准备慢慢吃慢慢聊,而排队的人当中有些人很饿很着急吃完还有事,这时你如果先点几个招牌菜解解馋,然后将座位让出来,重新排队,并且排队的人当中像你这样的都这么做,那些排队中心急如焚的人真是是幸福感爆棚,外婆家的老板也笑弯了腰。你让出座位重新排队的爱心行为就是 await Task.Yield()
。
祝大家程序员节快乐!
补充 - 后来发现的相关链接:
出让执行权:Task.Yield, Dispatcher.Yield: https://walterlv.com/post/yield-in-task-dispatcher.html
原文地址: https://www.cnblogs.com/dudu/p/task-yield.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
终于明白了 C# 中 Task.Yield 的用途相关推荐
- 出让执行权:Task.Yield, Dispatcher.Yield
一个耗时的任务,可以通过 Task.Yield 或者 Dispatcher.Yield 来中断以便分割成多个小的任务片段执行. Yield 这个词很有意思,叫做"屈服"" ...
- 看完这篇文章之后,终于明白了编译到底怎么回事。
看完这篇文章之后,终于明白了编译到底怎么回事. 1 对于同一个语句,有如下三种:高级语言.低级语言.机器语言的表示 C语言 a=b+1; 汇编语言 mov -0xc(%ebp),%eax add ...
- 15.3 Task Task.Yield和Task.Delay说明
https://blog.csdn.net/hurrycxd/article/details/79827958 书上看到一个Task.Yield例子,Task.Yield方法创建一个立即返回的awai ...
- 看完这篇文章之后,终于明白了编译到底怎么回事
看完这篇文章之后,终于明白了编译到底怎么回事. 1 对于同一个语句,有如下三种:高级语言.低级语言.机器语言的表示 C语言 a=b+1; 汇编语言 mov -0xc(%ebp),%eax add ...
- python里的关键字有哪些_Python中的yield关键字做了什么?
Python中的yield关键字做了什么 要理解yield做了什么,就必须明白生成器(generators)为何物,而在明白生成器之前还要知道迭代器(iterables). 1.迭代器 当我们创建一个 ...
- 出让执行权:Task.Yield, Dispathcer.Yield
Yield 这个词很有意思,叫做"屈服""放弃""让步",字面意义上是让出当前任务的执行权,转而让其他任务可以插入执行.Task.Dispa ...
- python可以做运动控制卡吗_今天,终于明白了运动控制器和运动控制卡的区别
原标题:今天,终于明白了运动控制器和运动控制卡的区别 运动控制器是完整的.独立的硬件平台,运动控制卡则需要一个载体(一个系统运行平台,必须基于PC). 一.从安装使用方式来看 运动控制卡,一般是PCI ...
- Python3中的yield from语法
Python3中的yield from语法 by Kay Zheng Tags: python, 协程, generator 30 March 2014 2016-2-23 更新 這篇文章是兩年前 ...
- php 对mvc的认识,【PHP】MVC框架为何这么难! 4年后终于明白了,被ThinkPHP害得!...
[PHP]MVC框架为什么这么难!!! 4年后终于明白了,被ThinkPHP害得!! 本帖最后由 default7 于 2014-05-15 18:39:05 编辑 这个帖子送给那些被ThinkPHP ...
最新文章
- 下图为双总线结构机器的数据通路_图像采集卡常见的三种总线结构
- nginx+php+memcache高速缓存openresty)
- 关于COUNT STOPKEY的工作机制
- 来谈谈JAVA面向对象 - 鲁班即将五杀,大乔送他回家??
- 你知道C#中的Lambda表达式的演化过程吗?
- C++基础之返回数组
- 目前项目wordpress插件记录
- 每个项目都不同:支持一个摄像头,到现在还没搞好
- [2]Selenium学习系列---- FirePath的安装和使用
- python分析并爬取起点中文网的章节数据,最后保存为txt文档
- 计算机中word音乐符号在哪里找,word音乐符号怎么打
- Excel小问题 - 前三个非空单元格数值之和
- 再回顾SGX初始化(一)——环境检查
- numpy库的函数学习
- Hadoop详解(七)——Hive的原理和安装配置和UDF,flume的安装和配置以及简单使用,flume+hive+Hadoop进行日志处理
- 辅警小丁同志 灵宝西站派出所第一警务区赵桥
- 我的2020java社招岗面经,阿里巴巴社招面试经历(Java工程师方向)
- win10U盘重装无法进行,一直转圈加载,不进入安装界面超过半小时
- 【Java】9、Java IO 流
- 实操-安装esxi6.0和配置
热门文章
- 常用的加密算法---数字摘要
- [BOOST] BOOST::Format
- MYSQL技术连环斩-MYSQL简述
- C# 线程问题之争用条件
- Avalonia跨平台入门第二十三篇之滚动字幕
- .NET6之MiniAPI(二十):实体验证FluentValidation
- Workflow Core + asp.net core 5.0 实现简单审批工作流
- 在asp.net core 下定义统一的入参和出参格式
- Masuit.Tools,一个免费的轮子
- Dotnet的数据定位和匹配