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会将转化得到 ...
随机推荐
- Java方法调用数组,是否改变原数组元素的总结
Java方法调用数组,是否改变原数组元素的总结 //个人理解, 欢迎吐槽 注意String是引用型变量, 我的理解也就是指向型, 指向一个数据或变量, 画图理解最容易, string 指向的 数据的值 ...
- Python学习-第三节part1: 关于函数
一 为何要用函数之不用函数的问题 #1.代码的组织结构不清晰,可读性差 #2.遇到重复的功能只能重复编写实现代码,代码冗余 #3.功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护 ...
- PTA数据结构与算法题目集(中文) 7-6
PTA数据结构与算法题目集(中文) 7-6 7-6 列出连通集 (25 分) 给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N−1编号.进行搜索时, ...
- Scratch 怎么打开SB文件怎么打开
扩展名是.sb( )的文件均可以用匹配版本的scratch或比匹配版本高的scratch打开,列表如下:类型 可打开.sb ···1.4(1.3).sb2 ···2.0.sb3··· 3.0或3.0b ...
- 批处理 bat 查询局域网内在线电脑IP
查看自己局域网的IP和物理网卡地址可以在 WIN+R –> 打开cmd 键入 arp -a 可以看到局域网中所有的在线IP COLOR 0A CLS @ECHO Off Title 查询局域网内 ...
- 30 HashSet
/* * 使用HashSet存储字符串并遍历 * * Set的特点: * 无序(存储和读取的顺序可能不一样) * 不允许重复 * 没有整数索引 于List正好相反 */ public class Ha ...
- Python设计模式(8)-抽象工厂
# coding=utf-8 这种方式反倒把事情做复杂了 可取之处在于有了更高层次的抽象 class IEmployee: def insert_employee(self): pass class ...
- app扫描二维码登陆
先说明一下实现原理: 如同微信扫描登陆一样,就是一种pc的自动登陆授权.在网站首页得有切换登陆的选项:密码登陆 扫码登陆 当用户切换到扫码登陆时,向服务器请求一次获得一个唯一的uukey 利用这个uu ...
- std::string::copy函数
size_t copy (char* s, size_t len, size_t pos = 0) const;
- 智能指针 unique_ptr
unique_ptr 不共享它的指针.它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法. 1.不能进行复制构造和赋值操作(unique ...