Task和ThreadPool的功能类似,可以用来创建一些轻量级的并行任务。对于将一个任务放进线程池 ThreadPool.QueueUserWorkItem(A);
这段代码用Task来实现的话,方式如下: Task.Factory.StartNew(A);
这两端代码的使用和实现的功能都十分相似。但和TheadPool相比,Task有着更多的功能,更加方便我们使用。
假如我们要创建三个任务,并等待它们完成。这个功能用TheadPool实现如下:
using (ManualResetEvent mre1 = new ManualResetEvent(false)) using (ManualResetEvent mre2 = new ManualResetEvent(false)) using (ManualResetEvent mre3 = new ManualResetEvent(false)) { ThreadPool.QueueUserWorkItem(delegate { A(); mre1.Set(); }); ThreadPool.QueueUserWorkItem(delegate { B(); mre2.Set(); }); ThreadPool.QueueUserWorkItem(delegate { C(); mre3.Set(); }); WaitHandle.WaitAll(new WaitHandle[] { mre1, mre2, mre3 }); }
用Task类实现起来就相对简单多了:
Task t1 = Task.Factory.StartNew(delegate { A(); }); Task t2 = Task.Factory.StartNew(delegate { B(); }); Task t3 = Task.Factory.StartNew(delegate { C(); }); t1.Wait(); t2.Wait(); t3.Wait();
或者我们还可以这么写:
Task t1 = Task.Factory.StartNew(delegate { A(); }); Task t2 = Task.Factory.StartNew(delegate { B(); }); Task t3 = Task.Factory.StartNew(delegate { C(); }); Task.WaitAll(t1, t2, t3);
下面我们来简单的介绍一下Task的基本用法:
创建Task
创建Task有两种方式
- 通过构造函数创建 Task t1 = new Task(A);
- 通过TaskFactory创建 Task t1 = Task.Factory.StartNew(A);
这两种方式其实是一样的,第一种方式里面也传入了默认的TaskFactory——Task.Factory。TaskFactory起着对Task进行创建和调度管理的作用,类似于以前CTP版中的TaskManager,关于这个对象,后续会单独写一篇文章介绍。
开始运行Task
在上述两种创建Task方式中,方式1创建的Task并没有立即执行,需要手动调用t1.Start()来执行(类似于线程,需要手动执行)。而方式2创建的Task是立即执行的(类似于线程池,是自动执行的),从这两种方式的函数名称也可以看出这一点。
等待Task完成
等待Task完成的也有两种:
- 调用Task的成员函数t.Wait()。
- 调用Task的静态函数Task.WaitAll()或Task.WaitAny()。
这两种方式和.net中常用的WaitHandle差不多,这里就不多介绍了。
取消Task
取消Task的方式较CTP的时候复杂和强大了不少,后续加一个单独的篇章单独介绍。
异常处理
当Task在执行过程中发生异常时,该异常会在Wait或WaitAll等函数中重新throw。可以通过Task的Exception属性来获取发生的异常。
var t1 = Task.Factory.StartNew(() => { throw new Exception("t1 error occor"); }); var t2 = Task.Factory.StartNew(() => { throw new Exception("t2 error occor"); });
try { Task.WaitAll(t1, t2); } catch (Exception) { Console.WriteLine(t1.Exception.InnerException.Message); Console.WriteLine(t2.Exception.InnerException.Message); }
获取Task的返回值
在CTP版本中,是通过Fucture<>类来获取带返回值的Task的,现在已经将类改名为Task<>了,从而实现命名方式的统一。使用方式几乎一致,就是多了一个Result属性,可以在Task执行完成后获取返回值。示例如下:
); t1.Wait(); Console.WriteLine(t1.Result);
其它
在Task中还有不少非常有用的任务调度和错误处理等的方法和属性,它们使得并发操作变得更为强大和简单,以后会陆续介绍这些知识。
.Net4.0并行库介绍——Task的更多相关文章
-
.Net4.0并行库介绍——Cancellation Framework
在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用. 同步模式下的取消: 一种比较常见的需要支持取消功能的的是一些 ...
-
.Net4.0如何实现.NET4.5中的Task.Run及Task.Delay方法
前言 .NET4.0下是没有Task.Run及Task.Delay方法的,而.NET4.5已经实现,对于还在使用.NET4.0的同学来说,如何在.NET4.0下实现这两个方法呢? 在.NET4.0下, ...
-
C#当中的多线程_任务并行库(上)
复习: 第三章内容中我们提到了三种异步编程模型,这里简单复习一下,分别如下 1.APM(异步编程模式):形如Beginxxx,Endxxx. 2.EAP(基于事件的异步编程模式):这个我们在.net中 ...
-
.NET异步程序设计之任务并行库
目录 1.简介 2.Parallel类 2.0 Parallel类简介 2.1 Parallel.For() 2.2 Parallel.ForEach() 2.3 Parallel.Invoke() ...
-
C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)
学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...
-
.Net4.0 任务(Task)[转]
.Net4.0 任务(Task) 任务(Task)是一个管理并行工作单元的轻量级对象.它通过使用CLR的线程池来避免启动专用线程,可以更有效率的利用线程池.System.Threading.Tasks ...
-
.Net4.0 任务(Task)
任务(Task)是一个管理并行工作单元的轻量级对象.它通过使用CLR的线程池来避免启动专用线程,可以更有效率的利用线程池.System.Threading.Tasks 命名空间下任务相关类一览: 类 ...
-
C#多线程编程系列(五)- 使用任务并行库
目录 1.1 简介 1.2 创建任务 1.3 使用任务执行基本的操作 1.4 组合任务 1.5 将APM模式转换为任务 1.6 将EAP模式转换为任务 1.7 实现取消选项 1.8 处理任务中的异常 ...
-
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...
随机推荐
-
理解C# 4 dynamic(4) – 让人惊艳的Clay
Clay非常类似于ExpandoObject, 可以看做是ExpandoObject的加强版. 它们能够让我们在不需要定义类的情况下,就构建出我们想要的对象.Clay和ExpandoObject相比, ...
-
dofile执行ANDROID APK里面的文件
我使用dofile执行APK文件是不行的,比如 dofile("assets/res/flist")只能先拷贝到writablePath然后再dofile拿到数据后再清除这个临时文 ...
-
launch文件
launch在ROS应用中,每个节点通常有许多参数需要设置,为了方便高效操作多个节点,可以编写launch文件,然后用roslaunch命令运行roslaunch: roslaunch [option ...
-
Delphi 停靠技术的应用
一.基础知识介绍 1.VCL组件的基础知识 在TWinControl类中有一个DockSite属性(boolean),它的作用是是否允许别的控件停靠在它的上面:在TControl类中有一个DragKi ...
-
基于MFC的socket编程(异步非阻塞通信)
对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清, ...
-
Javascript:一个优雅的时钟
实现效果: 准备工作: 1# 定时器 相关知识了解 2#javascript Date(日期)对象 3# 准备效果所用图片 实现原理: 1# 获取当前时间: var time=new Date(); ...
-
Qt在Linux环境下应用程序字体模糊的解决方法(先改成使用默认字体,然后使用qtconfig配置)
这两天一直在用Qt实现一个跨平台的软件.软件之前在Windows上编写的,后来放到里Ubuntu 10.10下编译.程序运行时遇到一个很棘手的问题,界面文本非常模糊.后来在网上查阅了好几天的资料,经历 ...
-
Windows Service 学习系列(三)——循环引擎 ICycleEngine
摘要:转载:https://www.cnblogs.com/zhuweisky/archive/2009/09/01/1557792.html#undefined 1.缘起: 有些系统需要每隔一段时间 ...
-
fail to resolve com.umeng.analytics:analytics:latest.integration
今天友盟接入的时候,他娘的居然提示我这个友盟jar包拉不下来 明明之前还好好的,而且别的什么东西都没问题,就这个有问题 原来使用的是 compile "com.umeng.analytics ...
-
Hello2 分析
一.打开GreetingServlet.java文件以查看它 hello2应用程序是一个web模块,hello2应用程序的行为几乎与hello1应用程序相同,但是它是使用Java Servlet技术实 ...