你好,我是阿辉。

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

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

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

为了解决这个问题,在.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;
}

这里我们声明并运行了线程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#多线程开发-任务并行库04的更多相关文章

  1. C#当中的多线程_任务并行库(上)

    复习: 第三章内容中我们提到了三种异步编程模型,这里简单复习一下,分别如下 1.APM(异步编程模式):形如Beginxxx,Endxxx. 2.EAP(基于事件的异步编程模式):这个我们在.net中 ...

  2. 谈谈C#多线程开发:并行、并发与异步编程

    阅读导航 一.使用Task 二.并行编程 三.线程同步 四.异步编程模型 五.多线程数据安全 六.异常处理 概述 现代程序开发过程中不可避免会使用到多线程相关的技术,之所以要使用多线程,主要原因或目的 ...

  3. C#当中的多线程_任务并行库(下)

    4.8 处理任务中的异常 下面这个例子讨论了任务当中抛出异常,以及任务异常的获取     class Program     {         static void Main(string[] a ...

  4. C#当中的多线程_任务并行库(中)

    发现自己有点懒了!也可能是越往后越难了,看书理解起来有点费劲,所以这两天就每天更新一点学习笔记吧. 4.5 将APM模式转化为任务 书上提供的三种方式 方式一: class Program       ...

  5. Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介

    Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...

  6. C#多线程编程系列(五)- 使用任务并行库

    目录 1.1 简介 1.2 创建任务 1.3 使用任务执行基本的操作 1.4 组合任务 1.5 将APM模式转换为任务 1.6 将EAP模式转换为任务 1.7 实现取消选项 1.8 处理任务中的异常 ...

  7. iOS开发常用第三方库

    UI 动画 网络相关 Model 其他 数据库 缓存处理 PDF 图像浏览及处理 摄像照相视频音频处理 响应式框架 消息相关 版本新API的Demo 代码安全与密码 测试及调试 AppleWatch ...

  8. .NET异步程序设计之任务并行库

    目录 1.简介 2.Parallel类 2.0 Parallel类简介 2.1 Parallel.For() 2.2 Parallel.ForEach() 2.3 Parallel.Invoke() ...

  9. DELPHI XE7 新的并行库

    DELPHI XE7 的新功能列表里面增加了并行库System.Threading, System.SyncObjs. 为什么要增加新的并行库? 还是为了跨平台.以前要并行编程只能从TThread类继 ...

随机推荐

  1. element UI rules prop对应关系

  2. ASP.NET中Textbox后的必填验证控件RequiredFieldValidator的使用方法。

    制作效果如下: 实现方法: 1. 拖动RequiredFieldValidator控件到相应的textbox后位置,点击属性面板,输入ErroMessage相应信息,更改ForeColor为红色 设置 ...

  3. 说说Java异步调用的几种方式

    日常开发中,会经常遇到说,前台调服务,然后触发一个比较耗时的异步服务,且不用等异步任务的处理结果就对原服务进行返回.这里就涉及的Java异步调用的一个知识.下面本文尝试将Java异步调用的多种方式进行 ...

  4. vue实现单点登录的N种方式

    最近项目停工了,RageFrame的学习暂时告一段落,这一篇给大家分享下有关单点登录的相关知识,并提供一些demo给大家参考,希望对想了解的朋友有一些帮助. 话不多说,先上原理(借鉴地址:https: ...

  5. linux中的防火墙netfilter iptables

    目录 一.Linux防火墙基础 1.1 ptables的表.链结构 1.2 数据包控制的匹配流程 二.编写防火墙规则 1.iptables的安装 2.1 基本语法.控制类型 一般在生产环境中设置网络型 ...

  6. 迈入 8K 时代,AI 驱动超高清 “视” 界到来

    2021 年,超高清迈入 "8K" 时代.超高清视频将带来全新视听体验,但超高清生产在内容生产层面也面临着超高清存量少.生产设备更新换代慢.制作周期成倍增加的困境.在 7 月 10 ...

  7. 字符串连接 strcat

    1 //字符串连接 strcat 2 //将一个字符串连接到另一个字符串的末尾,组合成一个新字符串 3 4 #include<stdio.h> 5 #include<stdlib.h ...

  8. 网安日记④之搭建域环境(domain)并且配置域

    搭建域环境(domain)并且配置域 什么是域 域就是将多台计算机在逻辑上组织到一起,进行集中管理,也就是创建在域控制器上的组,将组的账户信息保存在活动目录中.域组可以用来控制域内任何一台计算机资源的 ...

  9. Linux-shell编程经验记录

    Linux-shell编程经验总结 1.接收用户输入 #读取用户输入并且将输入保存到input变量中 read -p "请输入:" input #也可以先输出信息再进行读取,这里的 ...

  10. configmap使用方法

    说明: kubernetes统一配置管理方案configmap,实现将配置文件从容器镜像中解耦,增强应用的可移植性.数据可直接注入pod对象中,为容器所使用,注入方式有挂载为存储卷和传递为环境变量两种 ...