你好,我是阿辉。

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

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

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

为了解决这个问题,在.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. 手撸一个SpringBoot-Starter

    1. 简介 通过了解SpringBoot的原理后,我们可以手撸一个spring-boot-starter来加深理解. 1.1 什么是starter spring官网解释 starters是一组方便的依 ...

  2. 题解 P6688 可重集

    己所欲者,杀而夺之,亦同天赐 解题思路 一定不要用自动溢出的 Hash!!!!!!! 我真的是调吐了... 思路非常简单明了 : 需要我们创新一下 Hash. 首先我们的 Hash 要满足无序性.. ...

  3. 一口气说出 Redis 16 个常见使用场景!

    1.缓存 String类型 例如:热点数据缓存(例如报表.明星出轨),对象缓存.全页缓存.可以提升热点数据的访问数据. 文章首发于:http://ht5n8.cn/LEc6v 2.数据共享分布式 St ...

  4. 题解AGC004C

    题目 . 样例 AGC 好评. 题意:让你在一个 \(H \times W\) 的方格纸上找两个连通块,使得他们的重合部分就是输入中给的部分. 先放个样例. 输入: 5 5 ..... .#.#. . ...

  5. 靶机CH4INRULZ_v1.0.1

    nmap开路. root@kali:~# nmap -sP 192.168.1.* //拿到靶机地址192.168.1.8 root@kali:~# nmap -p- -sS -v -sV 192.1 ...

  6. 去除Windows-XP系统下的关机功能

    by han 去除Windows-XP系统下的关机功能 一.去除"开始菜单"中"关机"功能 1.点击左下角"开始",然后"运行&q ...

  7. String s="a"+"b"+"c",到底创建了几个对象?

    首先看一下这道常见的面试题,下面代码中,会创建几个字符串对象? String s="a"+"b"+"c"; 如果你比较一下Java源代码和反 ...

  8. Ubuntu安装ssh,及失败解决方案

    网上有很多介绍在Ubuntu下开启SSH服务的文章,但大多数介绍的方法测试后都不太理想,均不能实现远程登录到Ubuntu上,最后分析原因是都没有真正开启ssh-server服务.最终成功的方法如下: ...

  9. Linux中的DNS主从解析

    目录 一.主服务器配置(紧接着正反解析实验) 1.1.修改区域配置文件 二.从服务器配置(启动另一台虚拟机) 2.1.安装服务 2.2.修改主配置文件 2.3.修改区域配置文件 2.4.修改dns服务 ...

  10. c# 执行python方法

    在C#使用Python脚本文件要注意的的是,首先要将IronPython2.7安装路径中的两个dll文件添加到C#引用中一个是IronPython.dll,另一个是Microsoft.Scriptin ...