c#中task与thread区别及其使用的方法示例

作者:looper.zhuo 时间:2021-08-06 13:59:10 

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启动之后才执行。

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

2.我们来看看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。

3.下面演示几个控制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就往下继续执行。

4.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);

5.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还在继续跑。

6.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执行完。

6.task死锁的问题

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

7.对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区别及其使用的方法示例

 

来源:https://blog.csdn.net/qq_40677590/article/details/102797838

标签:c#,task,thread,区别
0
投稿

猜你喜欢

  • JAVA JDK8 List分组的实现和用法

    2023-11-26 09:56:11
  • Java解决约瑟夫问题代码实例

    2023-09-20 19:17:02
  • C#如何使用Task执行异步操作

    2023-01-12 03:34:41
  • 一文搞懂Java中的序列化与反序列化

    2021-11-22 00:26:45
  • 如何解决修改StaticText的字体

    2023-05-25 08:40:14
  • 详解Java线程同步器CountDownLatch

    2023-08-23 18:42:39
  • springBoot加入thymeleaf模板的方式

    2023-11-25 14:31:23
  • java睡眠排序算法示例实现

    2022-04-01 00:13:32
  • Android 使用gradle打包Assets目录的案例

    2023-08-05 22:29:45
  • Java中static静态变量的初始化完全解析

    2023-11-27 21:03:39
  • Java源码解析之object类

    2023-11-05 00:46:28
  • spring security动态配置url权限的2种实现方法

    2021-06-25 15:31:12
  • springboot如何统一设置时区

    2022-01-26 18:16:39
  • Spring Boot Admin 进行项目监控管理的方法

    2021-09-01 23:39:19
  • 详解Java进阶知识注解

    2023-08-12 13:11:37
  • C#中XmlTextWriter读写xml文件详细介绍

    2022-01-26 05:13:48
  • Struts2 Result 参数详解

    2022-04-28 07:54:35
  • spring boot集成p6spy的最佳实践

    2023-04-11 23:40:36
  • Java String、StringBuffer与StringBuilder的区别

    2022-08-29 23:29:55
  • 使用sharding-jdbc实现水平分库+水平分表的示例代码

    2023-11-05 03:21:50
  • asp之家 软件编程 m.aspxhome.com