这篇文章主要介绍了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任务有两种模式:

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

publicvoidtest(){vartestTask=newTask(()=>{Console.WriteLine("taskstart");});testTask.Start();varfactoryTeak=Task.Factory.StartNew(()=>{Console.WriteLine("factorytaskstart");});}

2.我们来看看task的生命周期

vartestTask=newTask(()=>{Console.WriteLine("taskstart");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。

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

vartestTask=newTask(()=>{Console.WriteLine("taskstart");System.Threading.Thread.Sleep(2000);});testTask.Start();testTask.Wait();

vartestTask=newTask(()=>{Console.WriteLine("taskstart");System.Threading.Thread.Sleep(2000);});testTask.Start();varfactoryTeak=Task.Factory.StartNew(()=>{Console.WriteLine("factorytaskstart");});Task.WaitAll(testTask,factoryTeak);Console.WriteLine("end");

vartestTask=newTask(()=>{Console.WriteLine("taskstart");System.Threading.Thread.Sleep(2000);});testTask.Start();varfactoryTeak=Task.Factory.StartNew(()=>{Console.WriteLine("factorytaskstart");});Task.WaitAny(testTask,factoryTeak);Console.WriteLine("end");

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

4.task的回调执行

vartestTask=newTask(()=>{Console.WriteLine("taskstart");System.Threading.Thread.Sleep(2000);});testTask.Start();varresultTest=testTask.ContinueWith<string>((Task)=>{Console.WriteLine("testTaskend");return"end";});Console.WriteLine(resultTest.Result);

5.task的取消

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

vartokenSource=newCancellationTokenSource();//创建取消task实例vartestTask=newTask(()=>{for(inti=0;i<6;i++){System.Threading.Thread.Sleep(1000);}},tokenSource.Token);Console.WriteLine(testTask.Status);tokenSource.Token.Register(()=>{Console.WriteLine("taskistocancel");});tokenSource.Cancel();Console.WriteLine(testTask.Status);

输出结果:

Created
task is to cancel
Canceled

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

vartokenSource=newCancellationTokenSource();//创建取消task实例vartestTask=newTask(()=>{for(inti=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("taskistocancel");});tokenSource.Cancel();Console.WriteLine(testTask.Status);for(inti=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还在继续跑。

6.task的嵌套

varparentTask=newTask(()=>{varchildTask=newTask(()=>{System.Threading.Thread.Sleep(2000);Console.WriteLine("childTasktostart");});childTask.Start();Console.WriteLine("parentTasktostart");});parentTask.Start();parentTask.Wait();Console.WriteLine("end");

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

varparentTask=newTask(()=>{varchildTask=newTask(()=>{System.Threading.Thread.Sleep(2000);Console.WriteLine("childTasktostart");},TaskCreationOptions.AttachedToParent);childTask.Start();Console.WriteLine("parentTasktostart");});parentTask.Start();parentTask.Wait();Console.WriteLine("end");

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

6.task死锁的问题

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

7.对Spinlock的使用

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

SpinLockslock=newSpinLock(false);vartestLock=newobject();longsum1=0;longsum2=0;longsum3=0;Parallel.For(0,100000,i=>{sum1+=i;});Parallel.For(0,100000,i=>{boollockTaken=false;try{slock.Enter(reflockTaken);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:

task:

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