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会将转化得到 ...
随机推荐
- 大数据篇:Hive
大数据篇:Hive hive.apache.org Hive是什么? Hive是Facebook开源的用于解决海量结构化日志的数据统计,是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射 ...
- ElasticSearch、IK分词器、Head Master安装-----Windows
一.下载 地址:https://www.elastic.co/cn/downloads/elasticsearch 历史版本:找到下面这句话 然后双击 Not the version you're l ...
- B 火车
时间限制 : 10000 MS 空间限制 : 565536 KB 评测说明 : 1.5s,512m 问题描述 A 国有n 个城市,城市之间有一些双向道路相连,并且城市两两之间有唯一路径.现在有火车 ...
- 我是如何从通信转到Java软件开发工程师的?
我的读者里面有绝大部分都是在校学生,有本科的,也有专科的,我在微信里收到很多读者的提问,大部分问题都跟如何学习编程有关,有换专业自学的.有迷茫不知道如何学习的.有报培训班没啥效果的等等,我能感受到他们 ...
- 让你第一次认识到Java的内存管理
发现之前写的可读性不好,这次准备试试换风格,去掉长篇大论,觉得这个风格好的,麻烦点个赞啦 清理.JVM的妙处 大家以后都是程序员,假设你很不幸,需要自己交钱租房子. 你作为一个小穷人,租的房子到期了( ...
- [原创] 关于步科eview人机界面HMI的使用 - HMI做Slave - Modbus RS485通讯
做测试设备,或者自动化设备常常用到HMI 触摸屏 我有个案子用到了 步科的eview 触摸屏 型号 ET070 我的是单片机主板 控制 HMI显示,通讯用485 MODBUS 单片机板充当 主控 , ...
- div实现富文本编辑框
ocument.execCommand()方法处理Html数据时常用语法格式如下:document.execCommand(sCommand[,交互方式, 动态参数]) 其中:sCommand为指令参 ...
- find的基本查询命令《二》
Linux find命令详解 由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下.即使系统中含有网络文件系统( NFS),find命令在该文件系统中同样有效,只你 ...
- Vulnhub DC-3靶机渗透
修改错误配置 打开了ova文件会发现,怎么也找不到DC-3的ip地址,估计是网卡出了问题. 那么就先配置下网卡. 进入上面这个页面之前按e. 将这里的ro 替换为 rw signie init=/bi ...
- 从String 聊源码解读
@ 目录 源码实现 构造方法 equals 其他方法 常见面试题 你真的了解String吗?之前一篇博客写jvm时,就觉得String可以单独拎出来写一篇博客,毕竟几乎所有的面试都是以String开始 ...