C#开发入门到精通之C#多线程开发之任务并行库
小职 2021-09-09 来源 :Andy阿辉 阅读 1290 评论 0

摘要:本文主要介绍了C#开发入门到精通之C#多线程开发之任务并行库,通过具体的内容向大家展现,希望对大家C#开发的学习有所帮助。

本文主要介绍了C#开发入门到精通之C#多线程开发之任务并行库,通过具体的内容向大家展现,希望对大家C#开发的学习有所帮助。

C#开发入门到精通之C#多线程开发之任务并行库

之前学习了线程池,知道了它有很多好处。

 

使用线程池可以使我们在减少并行度花销时节省操作系统资源。可认为线程池是一个抽象层,其向程序员隐藏了使用线程的细节,使我们可以专心处理程序逻辑,而不是各种线程问题。

 

但也不是说我们所有的项目中都上线程池,其实它也有很多弊端,比如我们需要自定义使用异步委托的方式才可以将线程中的消息或异常传递出来。这些如果在一个大的软件系统中,会导致软件结构过于混乱,各个线程之间消息传递来传递去的,如果发生没有处理掉的异常,很容易导致软件出现致命错误。

 

为了解决这个问题,在.Net Framework 4.0中引入了一个新的异步操作的API,它叫任务并行库(TPL)。

 

那么接下来,让我们一起来认识一下这个TPL,看看它到底有什么魔力可以把线程池中的棘手问题解决掉。

 

任务并行库

TPL又被认为是线程池的有一个抽象,其对程序员隐藏了线程池交互的底层代码,并只提供了更方便的细粒度的API。

 

TPL的核心是任务。一个任务代表一个异步操作,该操作可以通过多种方式运行,可以使用或不使用独立线程运行。

 

TPL有一个关键优势,就是一个任务可以通过多种方式和其它任务组合起来。

 

比如可以同时开启多个任务,等待所有任务完成,然后运行一个任务对之前所有任务的结果进行一些计算。

 

可以使用AggregateException来捕获底层任务内部所有异常,并允许单独处理这些异常。在C#5.0中已经内置了对TPL的支持,允许我们使用心得await和async关键字以平滑的、舒服的方式操作任务。

 

一、创建任务

 

可以通过下面三种方式来创建任务。

 

var a1 = new Task(()=>TastMethod("线程01"));

      a1.Start();

 

      Task.Run(()=>TastMethod("线程001"));    //已弃用

      Task.Factory.StartNew(()=>TastMethod("线程02"));

      Task.Factory.StartNew(() => TastMethod("线程03"),TaskCreationOptions.LongRunning);

 

      Console.ReadKey();

在最新的.NET 5.0中已经将任务快速启动方式Run,丢弃掉了。只能使用其余的两种。实例化的Tast属性,必须进行启动,任务才可以执行。其余的.NET已经做了内置,只需要使用就默认自动开启。

 

在线程3开启过程中,增加了TaskCreationOptions.LongRuning参数,它表示标记该任务为长时间运行,结果该任务将不会使用线程池,而在单独的线程中运行。然而根据运行该任务的当前任务调度程序,运行方式可能不同。

 

二、使用任务执行基本操作

 

下面介绍下从任务中得到其计算法返回的结果。

 

static void Main(string[] args)

       {    

           var a1 = new Task<int>(()=>TastMethod("线程01"));

           a1.Start();

           int result = a1.Result;             

           Console.WriteLine("result:" + result);

           Console.ReadKey();

       }

 

       static int TastMethod(string name)  

       {

           Console.WriteLine("线程名字:"+name+"Id:"+Thread.CurrentThread.ManagedThreadId+"是否属于线程池:"+Thread.CurrentThread.IsThreadPoolThread);

           return 40;

       }

 

 C#开发入门到精通之C#多线程开发之任务并行库

输出结果

 

这里我们声明并运行了线程01并等待结果,该任务会被放置在线程池中,并且主线程会等待,直到任务返回前一直处于阻塞状态。

 

其实也可以调用方法RunSynchronously()方法,使其特定运行在主线程。这是一个非常好的优化,可以避免使用线程池来执行非常短暂的操作。

 

三、处理任务中的异常

在异步任务中,对于异常的处理是非常重要的。

 

try

{

    var a1 = new Task<int>(() => TastMethod("线程01",2));

    a1.Start();

    int result = a1.Result;

    Console.WriteLine("result:" + result);

}

catch (Exception ex)

{

    Console.WriteLine(ex.Message);

}       

当程序启动时,创建了一个任务并尝试同步获取任务结果。Result属性的Get部分会使当前线程等待直到该任务结束,并将异常传播给当前线程。此时通过try/catch是很容易捕获到的(需要注意AggregateExceptiont,它被封装起来,)。

 

int result = a1.GetAwaiter().GetResult ;

上面这种情况无需封装异常,可以使用GetAwaiter和GetResult方法来访问任务结果。



我是小职,记得找我

✅ 解锁高薪工作

✅ 免费获取基础课程·答疑解惑·职业测评

C#开发入门到精通之C#多线程开发之任务并行库

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程