【导读】前不久,写过一篇关于Task的简短文章,通过评论和转载得到好评,刚好我昨晚又写了一篇实现简单的消息队列也提到了Task,难道不应该是看具体执行什么操作,再考虑最佳方案?本文我们再次通过简短内容谈谈Task
在评论中我提到,Task默认在线程池中运行,若执行耗时操作,此时极容易造成线程阻塞,最终导致线程池激增,很显然这是不正确的做法
然鹅,有的童鞋说了,给Task配置TaskCreationOptions.LongRunning即可解决耗时问题,此时将创建线程而非在线程池运行,要是执行耗时操作且无需知道返回结果(见上一篇),那干嘛不直接用Thread呢?
TaskCreationOptions.LongRunning直接创建线程,所以本文我们重点来讲讲该选项的正确使用方式,知其然,知其所以然。
再谈Task创建线程
我们一直在强调配置Task选项即可创建非线程池线程,那么我们是否可以通过一个简单例子来进行一次论证呢?如下代码和图展足以胜前言,至于细节,只能自行研究源码得知
证明:TaskCreationOptions.LongRunning创建非线程池线程
public static Format _colorify { get; set; }
static void Main(string[] args)
{_colorify = new Format(Theme.Light);int workerThreads, completionPortThreads;ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);_colorify.WriteLine(workerThreads.ToString(), Colors.bgDefault);_colorify.WriteLine(completionPortThreads.ToString(), Colors.bgDefault);ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);_colorify.WriteLine(workerThreads.ToString(), Colors.bgDefault);_colorify.WriteLine(completionPortThreads.ToString(), Colors.bgDefault);_colorify.WriteLine("---------------------------", Colors.bgSuccess);Task.Factory.StartNew(() =>{ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);_colorify.WriteLine(workerThreads.ToString(), Colors.bgWarning);_colorify.WriteLine(completionPortThreads.ToString(), Colors.bgWarning);ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);_colorify.WriteLine(workerThreads.ToString(), Colors.bgWarning);_colorify.WriteLine(completionPortThreads.ToString(), Colors.bgWarning);}, TaskCreationOptions.LongRunning);Console.Read();
}
同样,反其道行之,将LongRunning选项配置去除,则如下橙色部分所展示的线程池工作线程将减少1即(32766)
Task配置LongRunning是否可用于异步呢?
针对此问题的答案,如果我们不能立马给出答案,那么说明我们对异步还没有充分的理解,这里给出我对异步浅薄的定义:添加必要的逻辑(状态机),以允许释放当前线程,若长时间运行的异步操作已完成,则将结果返回到同一线程中,换言之,异步仅用于I/O操作。
我们来看如下一个例子
static async Task Main(string[] args)
{await AsyncTaskFactoryNew();Console.Read();
}static async Task AsyncTaskFactoryNew()
{await Task.Factory.StartNew(() => {// do your logic});
}
通过上述我们对异步的定义,然后再来看上述例子,结果显而易见,因为用了异步后将释放当前线程,也就是在第一次await后,通过Task选项所配置的创建非线程池线程将会被销毁,所以给Task配置创建非线程池线程结合使用异步相互矛盾,故毫无意义。
几篇简短内容,仍只是冰山一角,其中所涉及内容仍有许多供我们好好研究,比如如何利用Task实现断点续传中的暂停、取消呢?