文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

c#中task与thread区别是什么

2023-06-29 04:51

关注

这篇文章主要介绍了c#中task与thread区别是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

1.什么是thread

当我们提及多线程的时候会想到thread和threadpool,这都是异步操作,threadpool其实就是thread的集合,具有很多优势,不过在任务多的时候全局队列会存在竞争而消耗资源。thread默认为前台线程,主程序必须等线程跑完才会关闭,而threadpool相反。

总结:threadpool确实比thread性能优,但是两者都没有很好的api区控制,如果线程执行无响应就只能等待结束,从而诞生了task任务。

2.什么是task

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

3.创建一个task任务有两种模式:

使用factory创建会直接执行,使用new创建不会执行,必须等到start启动之后才执行。

 public void test()        {            var testTask = new Task(() =>            {                Console.WriteLine("task start");            });            testTask.Start();            var factoryTeak = Task.Factory.StartNew(() =>            {                Console.WriteLine("factory task start");            });        }

我们来看看task的生命周期

var testTask = new Task(() =>            {                Console.WriteLine("task start");                System.Threading.Thread.Sleep(2000);            });            Console.WriteLine(testTask.Status);            testTask.Start();            Console.WriteLine(testTask.Status);            Console.WriteLine(testTask.Status);                     testTask.Wait();            Console.WriteLine(testTask.Status);            Console.WriteLine(testTask.Status);

输出结果:

Created
task start
Running
Running
RanToCompletion
RanToCompletion

可以看出task确实是异步执行,并且wait很好地控制了task。

下面演示几个控制task的方法

     var testTask = new Task(() =>            {                Console.WriteLine("task start");                System.Threading.Thread.Sleep(2000);            });            testTask.Start();            testTask.Wait();
 var testTask = new Task(() =>            {               Console.WriteLine("task start");               System.Threading.Thread.Sleep(2000);            });            testTask.Start();var factoryTeak = Task.Factory.StartNew(() =>               {                                   Console.WriteLine("factory task start");               });              Task.WaitAll(testTask, factoryTeak);              Console.WriteLine("end");
 var testTask = new Task(() =>            {                Console.WriteLine("task start");                System.Threading.Thread.Sleep(2000);            });            testTask.Start(); var factoryTeak = Task.Factory.StartNew(() =>               {                                    Console.WriteLine("factory task start");                });                Task.WaitAny(testTask, factoryTeak);                Console.WriteLine("end");

通过wait()对单个task进行等待,Task.waitall()对多个task进行等待,waitany()执行任意一个task就往下继续执行。

task的回调执行

  var testTask = new Task(() =>            {                Console.WriteLine("task start");                System.Threading.Thread.Sleep(2000);            });            testTask.Start();            var resultTest = testTask.ContinueWith<string>((Task) => {                Console.WriteLine("testTask end");                return "end";            });            Console.WriteLine(resultTest.Result);

task的取消

首先创建一个取消task的令牌的实例,在不启动task直接取消:

var tokenSource = new CancellationTokenSource();//创建取消task实例            var testTask = new Task(() =>            {                for (int i = 0; i < 6; i++) {                    System.Threading.Thread.Sleep(1000);                }                           },tokenSource.Token);            Console.WriteLine(testTask.Status);            tokenSource.Token.Register(()=> {                Console.WriteLine("task is to cancel");            });            tokenSource.Cancel();            Console.WriteLine(testTask.Status);

 输出结果:

Created
task is to cancel
Canceled

如果task启动了真的取消了task?

  var tokenSource = new CancellationTokenSource();//创建取消task实例            var testTask = new Task(() =>            {                for (int i = 0; i <6; i++) {                    System.Threading.Thread.Sleep(1000);                }                           },tokenSource.Token);            Console.WriteLine(testTask.Status);            testTask.Start();            Console.WriteLine(testTask.Status);            tokenSource.Token.Register(()=> {                Console.WriteLine("task is to cancel");            });            tokenSource.Cancel();            Console.WriteLine(testTask.Status);            for (int i = 0; i < 10; i++)            {                System.Threading.Thread.Sleep(1000);                Console.WriteLine(testTask.Status);            }

输出结果:

Created
WaitingToRun
task is to cancel
Running
Running
Running
Running
Running
Running
RanToCompletion
RanToCompletion
RanToCompletion
RanToCompletion
RanToCompletion

 可以看出其实并没有取消task,此时task还在继续跑。

task的嵌套

  var parentTask = new Task(()=> {                var childTask = new Task(() =>{                    System.Threading.Thread.Sleep(2000);                    Console.WriteLine("childTask to start");                });                childTask.Start();                Console.WriteLine("parentTask to start");            });            parentTask.Start();            parentTask.Wait();            Console.WriteLine("end");

此时为普通关联,父task和子task没影响

  var parentTask = new Task(()=> {                var childTask = new Task(() =>{                    System.Threading.Thread.Sleep(2000);                    Console.WriteLine("childTask to start");                }, TaskCreationOptions.AttachedToParent);                childTask.Start();                Console.WriteLine("parentTask to start");            } );            parentTask.Start();            parentTask.Wait();            Console.WriteLine("end");

此时为父task和子task关联,wait会一直等待父子task执行完。

task死锁的问题

我们可以设置最大等待时间,如果超过了等待时间,就不再等待,下面我们来修改代码,设置最大等待时间为5秒(项目中可以根据实际情况设置),如果超过5秒就输出哪个任务出错了

对Spinlock的使用

举例来说Parallel.for和Parallel.foreach是线程不安全的,有可能达不到你的预期,此时就需要加锁来解决此问题,我们可以加lock和spinlock(自旋锁)来解决

            SpinLock slock = new SpinLock(false);            var testLock= new object();            long sum1 = 0;            long sum2 = 0;            long sum3 = 0;            Parallel.For(0, 100000, i =>            {                sum1 += i;            });             Parallel.For(0, 100000, i =>            {                bool lockTaken = false;                try                {                    slock.Enter(ref lockTaken);                    sum2 += i;                }                finally                {                    if (lockTaken)                        slock.Exit(false);                }            });            Parallel.For(0, 100000, i =>            {                lock(testLock)                {                    sum3 += i;                };            });            Console.WriteLine("Num1的值为:{0}", sum1);            Console.WriteLine("Num2的值为:{0}", sum2);            Console.WriteLine("Num3的值为:{0}", sum3);

输出结果:

Num1的值为:1660913202
Num2的值为:4999950000
Num3的值为:4999950000

Num1的值为:2754493646
Num2的值为:4999950000
Num3的值为:4999950000

Num1的值为:4999950000
Num2的值为:4999950000
Num3的值为:4999950000

最后看看threadpoll和task的结构图:

threadpool:

c#中task与thread区别是什么

 task:

c#中task与thread区别是什么

感谢你能够认真阅读完这篇文章,希望小编分享的“c#中task与thread区别是什么”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯