c# Thread、ThreadPool、Task有什么区别,什么时候用,以及Task的使用

这三者都是为了处理耗时任务,都是异步的;

先说 Thread与ThreadPoll

前台线程:主程序必须等待线程执行完毕后才可退出程序。Thread默认为前台线程,也可以设置为后台线程

后台线程:主程序执行完毕后就退出,不管线程是否执行完毕。ThreadPool默认为后台线程

线程消耗:开启一个新线程,线程不做任何操作,都要消耗1M左右的内存

ThreadPoll是线程池 其目的是为了减少开启新线程消耗的资源(使用线程池中的空闲线程,不必在开启新线程,以及统一管理线程(线程池中的线程执行完毕后,回归到线程池里,等待新任务).

总结:ThreadPoll性能优于Thread,但是Thread和ThreadPoll对线程的控制都不是很好,例如线程等待(线程执行一段时间无响应后,直接停止线程,释放资源 等 都没有直接的API来控制 只能通过硬编码来实现,同时ThreadPool使用的是线程池全局队列,全局队列中的线程依旧会存在竞争共享资源的情况,从而影响性能。

然后task

Task的背后的实现也是使用了线程池线程,但它的性能优于ThreadPoll,因为它使用的不是线程池的全局队列,而是使用的本地队列,使线程之间的资源竞争减少。同时Task提供了丰富的API来管理线程、控制。但是相对前面的两种耗内存,Task依赖于CPU对于多核的CPU性能远超前两者,单核的CPU三者的性能没什么差别。

下面我们来写个简单的代码

创建Task有两种方法:

Task t = Task.Factory.StartNew(() => {

                Console.WriteLine("任务已启动....");

            });

Task t2 = new Task(() => {

                Console.WriteLine("开启一个新任务");

            });

            t2.Start();//任务已启动...

第一种方法不需要调用start 初始化后任务就开始了。

Task还可以随时取消正在执行的任务,请看下面的代码

static void Main(string[] args)

 {

CancellationTokenSource cts = new CancellationTokenSource();

            Task t3 = new Task(() => LongRunTask(cts.Token));

            t2.Start();

            Thread.Sleep(3000);

            cts.Cancel();

            Console.Read();

}

private static void LongRunTask(CancellationToken token)

        {

            while (true)

            {

                if (!token.IsCancellationRequested)

                {

                    Thread.Sleep(500);

                    Console.WriteLine(".");

                }

                else

                {

                    Console.WriteLine("任务取消了");

                    break;

                }

            }

        }

任务启动任务  当一个任务完成后 开启一个新的任务

Task task = new Task(() => { Thread.Sleep(5000); Console.WriteLine("Hello,"); Thread.Sleep(5000); });

            task.Start();

            Task newTask = task.ContinueWith(t => Console.WriteLine("开启了另一个任务"));

对于ContinueWith方法,我们可以配合TaskContinuationOptions枚举,得到更多我们想要的行为。

Task parant = new Task(() =>

            {

                new Task(() => Console.WriteLine("1")).Start();

                new Task(() => Console.WriteLine("2")).Start();

                new Task(() => Console.WriteLine("3")).Start();

                new Task(() => Console.WriteLine("4")).Start();

            });

            parant.Start();

值得注意的是,以上代码中所示的子任务的调用并不是以代码的出现先后为顺序来调用的。

任务工厂

在某些情况下,我们会创建大量的任务来满足业务,而恰好这些任务公用某个状态参数,为了避免大量的调用任务的构造器和一次又一次的传递参数,我们可以使用任务工厂来处理这种大量的创建任务,如下代码:

Task parent = new Task(() => 

            { 

                CancellationTokenSource cts = new CancellationTokenSource(); 

                TaskFactory tf = new TaskFactory(cts.Token); 

                var childTask = new[] 

                { 

                 tf.StartNew(()=>ConcreteTask(cts.Token)), 

                 tf.StartNew(()=>ConcreteTask(cts.Token)), 

                 tf.StartNew(()=>ConcreteTask(cts.Token)) 

                };

                Thread.Sleep(5000);//此处睡眠等任务开始一定时间后才取消任务 

                cts.Cancel(); 

            } 

            );

            parent.Start();//开始执行任务 

任务调度

任务的调度通过调度程序来实现的,目前,.NET 4.0内置两种任务调度程序:线程池任务调度程序(thread pool task scheduler)和同步上下文任务调度程序(synchronization context task scheduler)。默认情况下,应用程序使用线程池任务调度程序调用线程池的工作线程来完成任务,如受计算限制的异步操作。同步上下文任务调度程序通常使用UI线程来完成与Windows Forms,Windows Presentation Foundation(WPF)以及SilverLight应用程序相关的任务。

   可喜的是,.NET 4.0 提供了TaskScheduler抽象类供开发人员继承来实现自定义任务调度程序的开发,有兴趣的同学可以试试。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 然而,在今天这篇博客中,我们要知道的是,QueueUserWorkItem这个技术存在许多限制。其中最大的问题是没...
    北风知我意阅读 15,993评论 0 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 庄家,指能影响金融证券市场行情的大户投资者。通常是占有50%以上的发行量,有时庄家控量不一定达到50%,看各品种而...
    冯谷韵阅读 304评论 0 0
  • 安踏成功逆袭,李宁已跌落神坛。 五年之前,国内运动市场还是李宁的天下,可以说是一览众山小的存在。2012年之前,正...
    蜘蜘纺阅读 899评论 0 2
  • 坚持运动,没有什么是跑几圈不能解决的,如果有,就再跑几圈。 自我一周小结✔ 找到好位置,简历,ppt a new ...
    lnlakesh阅读 137评论 0 0