Task启动方式及源码探究
启动Task有几种方式:
1.Task.Run()
2.new TaskFactory.StartNew()
3.var t=new Task(); t.start();
平时用的最多是第一和第二种,那么他们之间有什么差异?接下来通过两个demo进行说明。
static void Main(string[] args)
{
for (int i = ; i < ; i++)
{
Task.Run(() => Sayhi("task"));
new TaskFactory().StartNew(() => Sayhi("taskfactory"));
} Console.ReadLine();
} public static void Sayhi(string method)
{
Console.WriteLine(method+":"+Thread.CurrentThread.ManagedThreadId);
}
运行结果:
task:5
taskfactory:4
taskfactory:6
task:7
task:5
task:6
taskfactory:7
taskfactory:5
task:4
taskfactory:6
通过以上结果可以猜测task跟taskfactory运行的模式基本一致,线程重复使用,猜测是通过线程池来调度。
接下来,我给TaskFactory().StartNew添加一个参数TaskCreationOptions.LongRunning
new TaskFactory().StartNew(() => Sayhi("taskfactory"),TaskCreationOptions.LongRunning);
运行结果:
task:9
task:9
task:4
taskfactory:5
task:6
task:7
taskfactory:8
taskfactory:10
taskfactory:11
taskfactory:12
如果你眼神犀利,相信已经看出其中的差异。没错,taskfactory每次运行都是一个新的线程,由此可以猜测TaskCreationOptions.LongRunning这个参数会决定task运行的命运,它将不会进入线程池,自己单飞了。
综上所述,有以下猜测:
1.Task.Run()与TaskFactory().StartNew()运行模式一致
2.都是线程池调度
3.TaskCreationOptions=TaskCreationOptions.LongRunning时,不由线程池调度。
为了验证猜测,让我们来翻一下源码。
Task.Run()
public static Task Run(Action action)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task.InternalStartNew(null, action, null, default(CancellationToken), TaskScheduler.Default,
TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark); }
new TaskFactory().StartNew()
public Task StartNew(Action action)
{
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask),
m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
}
可以看到,无论是Task.Run()还是new TaskFactory().StartNew()都是调用了Task.InternalStartNew方法,而Task.Run是默认的参数,TaskFactory().StartNew()拥有更多的自由度。由此验证猜测1。
继续跳进,最终调用ScheduleAndStart方法
internal void ScheduleAndStart(bool needsProtection)
{
try
{
// Queue to the indicated scheduler.
m_taskScheduler.InternalQueueTask(this); //调度任务
}
catch (ThreadAbortException tae)
{
AddException(tae);
FinishThreadAbortedTask(true, false);
}
}
m_taskScheduler实例就是上面的TaskScheduler.Default,来瞧瞧是装了什么东西
private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler(); public static TaskScheduler Default
{
get
{
return s_defaultTaskScheduler;
}
}
ThreadPoolTaskScheduler,瞧瞧这单词是不是有内味了,来,答案快水落石出了。
protected internal override void QueueTask(Task task)
{
if ((task.Options & TaskCreationOptions.LongRunning) != )
{
// Run LongRunning tasks on their own dedicated thread.
Thread thread = new Thread(s_longRunningThreadWork);
thread.IsBackground = true; // Keep this thread from blocking process shutdown
thread.Start(task);
}
else
{
// Normal handling for non-LongRunning tasks.
bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != );
ThreadPool.UnsafeQueueCustomWorkItem(task, forceToGlobalQueue);
}
}
看到这里相信不需要我再说什么了... 猜测验证成功。
总结以下:
1.Task.Run()是TaskFactory().StartNew()的其中一种形式。TaskFactory().StartNew()拥有更多自由度。
2.Task.Run()是线程池调度,TaskFactory().StartNew()参数TaskCreationOptions=TaskCreationOptions.LongRunning时,不由线程池调度。
源码链接:https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs
Task启动方式及源码探究的更多相关文章
- spring-boot-2.0.3之quartz集成,数据源问题,源码探究
前言 开心一刻 着火了,他报警说:119吗,我家发生火灾了. 119问:在哪里? 他说:在我家. 119问:具体点. 他说:在我家的厨房里. 119问:我说你现在的位置. 他说:我趴在桌子底下. 11 ...
- 浅谈.Net Core DependencyInjection源码探究
前言 相信使用过Asp.Net Core开发框架的人对自带的DI框架已经相当熟悉了,很多刚开始接触.Net Core的时候觉得不适应,主要就是因为Core默认集成它的原因.它是Asp.Net ...
- [Spark内核] 第34课:Stage划分和Task最佳位置算法源码彻底解密
本課主題 Job Stage 划分算法解密 Task 最佳位置算法實現解密 引言 作业调度的划分算法以及 Task 的最佳位置的算法,因为 Stage 的划分是DAGScheduler 工作的核心,这 ...
- spring-cloud-sleuth+zipkin源码探究
1. spring-cloud-sleuth+zipkin源码探究 1.1. 前言 粗略看了下spring cloud sleuth core源码,发现内容真的有点多,它支持了很多类型的链路追踪, ...
- Vue源码探究-全局API
Vue源码探究-全局API 本篇代码位于vue/src/core/global-api/ Vue暴露了一些全局API来强化功能开发,API的使用示例官网上都有说明,无需多言.这里主要来看一下全局API ...
- Vue源码探究-事件系统
Vue源码探究-事件系统 本篇代码位于vue/src/core/instance/events.js 紧跟着生命周期之后的就是继续初始化事件相关的属性和方法.整个事件系统的代码相对其他模块来说非常简短 ...
- Vue源码探究-状态初始化
Vue源码探究-状态初始化 Vue源码探究-源码文件组织 Vue源码探究-虚拟DOM的渲染 本篇代码位于vue/src/core/instance/state.js 继续随着核心类的初始化展开探索其他 ...
- Vue源码探究-源码文件组织
Vue源码探究-源码文件组织 源码探究基于最新开发分支,当前发布版本为v2.5.17-beta.0 Vue 2.0版本的大整改不仅在于使用功能上的优化和调整,整个代码库也发生了天翻地覆的重组.可见随着 ...
- Flink的Job启动TaskManager端(源码分析)
前面说到了 Flink的JobManager启动(源码分析) 启动了TaskManager 然后 Flink的Job启动JobManager端(源码分析) 说到JobManager会将转化得到 ...
随机推荐
- iOS 页面流畅技巧(1)
一.屏幕显示图像原理 首先明确两个概念:水平同步信号.垂直同步信号. CRT 的电子枪按照上图中的方式,从上到下一行一行的扫描,扫描完成后显示器就呈现一帧画面,随后电子枪回到初始位置继续下一次的扫描. ...
- k8s删除namespace一直处于terminating状态
k8s删除namespace一直处于terminating状态 当遇到删除ns是一直处于terminating情况可以用调k8s api进行删除. 1.创建api proxy. [root@node1 ...
- sNews1.7在wamp上的部署及运行
安装前的准备 Apache Server 必须开启 mod_rewrite 模块 MySQL 数据库版本在 4.x以上 PHP: >= 4.x 并且 <=5.6 1.我使用的是wampse ...
- PTA | 1029 旧键盘 (20分)
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及实际被输入的文字,请你列出肯定坏掉的那些键. 输入格式: 输入在 2 行中分别给出应该输入的文字.以及 ...
- Scratch2的鸡兔同笼
解题思路鸡兔同笼新算法:已知共有鸡和兔15只,共有40只脚,问鸡和兔各有几只.算法:假设鸡和兔训练有素,吹一声哨,它们抬起一只脚,(40-15=25) .再吹一声哨,它们又抬起一只脚,(25-15=1 ...
- Linux网络架设篇,虚拟机l系统中网卡设备名与配置文件不符如何处理?
很多情况下,当我们在虚拟机中安装好linux系统后,并不能成功连上网.当我们配置好相关IP地址后同样不能成功连接网络.并且会体会网卡名与配置名不符,这时候应该怎么办呢? 1.清空下面文件 /etc/u ...
- 28.1 api-- Object(toString equals)
/* * String toString() : 返回该对象的字符串表示 * return getClass().getName() + "@" + Integer.toHexSt ...
- "无用的文本"组件:<s> —— 快应用组件库H-UI
 <import name="s" src="../Common/ui/h-ui/text/c_tag_del"></import> ...
- 10-jmeter 测试soap协议v1.2版本请求
1.因为jmeter安装了第三方插件jmeter-plugins-manager.jar之后(具体安装看之前文章),此时就可简单直接测试soap协议1.2版本的请求了 2. 3.进行运行线程就可实现了 ...
- Linux c++ vim环境搭建系列(0)——简介
vim 学习 简介: 源码编译使用vim及其插件. 内容包含: vim的编译安装, llvm clang的编译安装, 插件youcompleteme的编译安装使用, 以及vim其他插件的使用. 搭建环 ...