一起谈.NET技术,.NET 4 并行(多核)编程系列之二 从Task开始

  前言:我们一步步的从简单的开始讲述,还是沿用我一直的方式:慢慢演化,步步为营。 本篇文章的议题如下:

  1.Task基础介绍

  2.Task的创建

  3.获取Task的执行结果

  4. 补充细节

  1.Task基础介绍

  首先我们还是来看看一段简单的代码:

  这里展示的只是一段简单的代码,不能显示出并行编程的特点。但是我们还是从最基本的开始看,慢慢进入深一点的话题。 如果你曾经用过.NET 中的多线程编程,比较一下,就会发现:这段代码虽然在底层还是使用了多线程,但是写法上却简化了很多,一行代码就实现了一个并行编程。

  下面我们就从Task类开始谈。 Task类是Task Programming Library(TPL)中最核心的一个类,下面我将会像大家展示如何使用一些方法来创建不同类型的Task,取消Task,等待Task执行完成,获取Task执行后的结果和对异常进行处理。 在开始讨论之前,我们首先快速的看看之前的代码: 这个命名空间将会是我们之后在讲述并行编程经常使用的一个。这个空间包含了很多与并行编程有关的类。

  还有一个要你使用的命名空间是:System.Threading,大家对这个应该比较熟悉了,之前的多线程编程常常使用到,这个空间下包含了一些在并行编程中用来协调数据的一些类。 上面代码中,最主要的代码如下:

Task.Factory.StartNew(()={Console.WriteLine("HelloWorld");});

  我们用静态方法:Task.Factory.StartNew()来创建了一个最简单的Task--在屏幕上打印一句话。这段代码确实简单,而且都没有任何输入和需要返回的结果。 下面我们就正式进入议题:

  2.Task的创建

   如果只是创建一个简单的Task,我们只要为该Task提供一个执行体就行了,执行体可以是一个委托delegate或者action。我们之前展示的那段代码就是采用了lambda表达式来作为Task的执行体。

  2.1 创建一个简单的Task

  为了执行一个简单的Task,一般进行以下步骤: 首先,要创建一个Task类的实例, 然后,传入一个System.Action委托,这个委托中的方法就是这个Task运行时你要执行的方法,而且这个委托必须作为Task构造函数的一个参数传入。我们在传入委托作为参数的时候有多种方式:传入匿名委托,Lambda表达式或者一个显示什么方法的委托。 最后,调用Task实例的Start()方法来运行。 当这个Task实例开始运行的时候,它就被传给了内部的一个task scheduler,这个scheduler负责把我们创建的task交给底下的线程去执行。 下面就看看代码:

代码

usingSystem;usingSystem.Threading.Tasks;namespaceListing_02{classListing_02{staticvoidMain(string[]args){//useanActiondelegateandanamedmethodTasktask1=newTask(newAction(printMessage));//useaanonymousdelegateTasktask2=newTask(delegate{printMessage();});//usealambdaexpressionandanamedmethodTasktask3=newTask(()=printMessage());//usealambdaexpressionandananonymousmethodTasktask4=newTask(()={printMessage();});task1.Start();task2.Start();task3.Start();task4.Start();//waitforinputbeforeexitingConsole.WriteLine("Mainmethodcomplete.Pressentertofinish.");Console.ReadLine();}staticvoidprintMessage(){Console.WriteLine("HelloWorld");}}}

  不知道大家注意到了没有,上面代码创建Task的方法和我们之前的第一段代码的创建Task的方法不同。在之前我们采用的是Task.Factory.StartNew()方法来创建的,这个方法创建Task并且开始运行Task,其实两端代码的结果是一样的,这里给出一点建议:如果这是想简单的创建一个Task,那么使用Factory.NewStart()来创建,很简便,如果像对所创建的Task附加更多的定制和设置特定的属性,那么还是得一步一步的按照我们说的那些步骤来。(详细的我们后续会介绍的) 2.1 为创建的Task传入参数  

   我们之前提过,在创建Task的时候,我们在构造函数中传入了一个System.Action的委托,如果我们想要把一些参数传入到Task中,那么我 们可以传入System.Actionobject的委托,其中的那个object就是我们传入的参数。还是给大家举个例子:

代码

usingSystem;usingSystem.Threading.Tasks;namespaceListing_04{classListing_04{staticvoidMain(string[]args){string[]messages={"Firsttask","Secondtask","Thirdtask","Fourthtask"};foreach(stringmsginmessages){TaskmyTask=newTask(obj=printMessage((string)obj),msg);myTask.Start();}//waitforinputbeforeexitingConsole.WriteLine("Mainmethodcomplete.Pressentertofinish.");Console.ReadLine();}staticvoidprintMessage(stringmessage){Console.WriteLine("Message:{0}",message);}}}

  注意:我们在传入参数后,必须把参数转换为它们原来的类型,然后再去调用相应的方法。例子中,因为System.Action对应的方法是printMessage()方法,而这个方法的要求的参数类型是string,所以要转换为string。  

  想向Task传入参素,只能用System.Actionobject
  3.获取Task的执行结果

  如果要获取Task的结果,那么在创建Task的时候,就要采用TaskT来实例化一个Task,其中的那个T就是task执行完成之后返回结果的类型。之后采用Task实例的Result属性就可以获取结果。 代码显示如下:

代码

staticvoidMain(string[]args){//createthetaskTaskinttask1=newTaskint(()={intsum=0;for(inti=0;i100;i++){sum+=i;}returnsum;});task1.Start();//writeouttheresultConsole.WriteLine("Result1:{0}",task1.Result);Console.ReadLine();}

  只有在task执行完成之后,才能获取到Result的值。 下面的代码展示了如何通过Task.Factory.StartNewT()创建一个Task,并且获取结果:

代码

staticvoidMain(string[]args){//createthetaskTaskinttask1=Task.Factory.StartNewint(()={intsum=0;for(inti=0;i100;i++){sum+=i;}returnsum;});//writeouttheresultConsole.WriteLine("Result1:{0}",task1.Result);Console.ReadLine();}

  4. 补充细节

  在创建Task的时候,Task有很多的构造函数的重载,一个主要的重载就是传入TaskCreateOptions的枚举: TaskCreateOptions.None:用默认的方式创建一个Task TaskCreateOptions.PreferFairness:请求scheduler尽量公平的执行Task(后续文章会将是,Task和线程一样,有优先级的) TaskCreateOptions.LongRunning:声明Task将会长时间的运行。 TaskCreateOptions.AttachToParent:因为Task是可以嵌套的,所以这个枚举就是把一个子task附加到一个父task中。

  最后要提到的一点就是,我们可以在Task的执行体中用Task.CurrentId来返回Task的唯一表示ID(int)。如果在Task执行体外使用这个属性就会得到null。 (熟悉WF的朋友,可以比较Task和WF的一些区别,因为我认为它们的设计思想很相近) 今天就到这里了,多谢大家!

时间: 2024-10-23 08:06:06

一起谈.NET技术,.NET 4 并行(多核)编程系列之二 从Task开始的相关文章

一起谈.NET技术,.NET并行(多核)编程系列之七 共享数据问题和解决概述

之前的文章介绍了了并行编程的一些基础的知识,从本篇开始,将会讲述并行编程中实际遇到一些问题,接下来的几篇将会讲述数据共享问题. 本篇的议题如下: 1.数据竞争 2.解决方案提出 3.顺序的执行解决方案 4.数据不变解决方案 在开始之前,首先,我们来看一个很有趣的例子: class BankAccount { public int Balance { get; set; } } class App { static void Main(string[] args) { // create the

.NET 4 并行(多核)编程系列之二 从Task开始

原文:.NET 4 并行(多核)编程系列之二 从Task开始 .NET 4 并行(多核)编程系列之二 从Task开始          前言:我们一步步的从简单的开始讲述,还是沿用我一直的方式:慢慢演化,步步为营.     本篇文章的议题如下:    1.Task基础介绍    2.Task的创建     3.获取Task的执行结果 4. 补充细节   系列文章链接: .NET 4 并行(多核)编程系列之一入门介绍 .NET 4 并行(多核)编程系列之二 从Task开始  .NET 4 并行(多

.NET 并行(多核)编程系列之五 Task执行和异常处理

原文:.NET 并行(多核)编程系列之五 Task执行和异常处理 .NET 并行(多核)编程系列之五 Task执行和异常处理 前言:本篇主要讲述等待task执行完成. 本篇的议题如下: 1. 等待Task执行完成 2. Task中的异常处理   系列文章链接: .NET 4 并行(多核)编程系列之一入门介绍 .NET 4 并行(多核)编程系列之二 从Task开始  .NET 4 并行(多核)编程系列之三 从Task的取消  .NET 4 并行(多核)编程系列之四 Task的休眠  .NET 并行

.NET并行(多核)编程系列之七 共享数据问题和解决概述

前言:之前的文章介绍了了并行编程的一些基础的知识,从本篇开始,将会讲述并行编程中实际遇到一些问题,接下来的几篇将会讲述数据共享问题. 本篇的议题如下: 数据竞争 解决方案提出 顺序的执行解决方案 数据不变解决方案 在开始之前,首先,我们来看一个很有趣的例子: class BankAccount{ public int Balance { get; set; }}class App{ static void Main(string[] args) { // create the bank acco

.NET并行(多核)编程系列之五 Task执行和异常处理

前言:本篇主要讲述等待task执行完成. 本篇的议题如下: 1. 等待Task执行完成 2. Task中的异常处理 首先注意一点:这里提到的"等待"和之前文章提到的"休眠"意思是不一样的: 等待:在等待一个task的时候,这个task还是在运行之中的,"等待"相当于在监听运行的task的执行情况. 休眠:让tasku不运行. 在上篇文章中介绍了如果从Task中获取执行后的结果:在Task执行完成之后调用Task.Result获取.其实也可以用其他

.NET 4并行(多核)编程系列之二 从Task开始

前言:我们一步步的从简单的开始讲述,还是沿用我一直的方式:慢慢演化,步步为营. 本篇文章的议题如下: 1.Task基础介绍 2.Task的创建 3.获取Task的执行结果 4. 补充细节 1.Task基础介绍 首先我们还是来看看一段简单的代码: 这里展示的只是一段简单的代码,不能显示出并行编程的特点.但是我们还是从最基本的开始看,慢慢进入深一点的话题. 如果你曾经用过.NET 中的多线程编程,比较一下,就会发现:这段代码虽然在底层还是使用了多线程,但是写法上却简化了很多,一行代码就实现了一个并行

.NET并行(多核)编程系列之六 Task基础部分完结篇

前言:之前的文章介绍了了并行编程的一些基本的,也注重的讲述了Task的一些使用方法,本篇很短,将会结束Task的基础知识的介绍. 本篇的主要议题如下: 1. 获取Task的状态 2. 执行晚加载的Task(Lazily Task) 3. 常见问题的解决方案 1.获取Task的状态 在.NET并行编程还有一个已经标准化的操作就是可以获取task的状态,通过Task.Status属性来得到的,这个属性返回一个System.Threading.Tasks.TaskStatus的枚举值. 如下: Cre

WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现

原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现         去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体机.要求有很炫的展示效果,要有一定的视觉冲击力,可触控操作.当然满足客户的要求也可以有其它途径.但鉴于咱是搞 .NET技术的,首先其冲想到的微软WPF方面,之前对WPF的了解与学习也只是停留在比较浅的层面,没有进一步深入学习与应用.所以在项目接来以后,也就赶

一起谈.NET技术,C# 4动态编程新特性与DLR剖析

近几年来,在TIOBE 公司每个月发布的编程语言排行榜 [1] 中,C# 总是能挤进前10 名,而在近10 年的编程语言排行榜中,C# 总体上呈现上升的趋势.C# 能取得这样的成绩,有很多因素在起作用,其中,它在语言特性上的锐意进取让人印象深刻( 图1 ). 图1 C#各版本的创新点 2010 年发布的 C# 4 ,最大的创新点是拥有了动态编程语言的特性. 1 动态编程语言的中兴 动态编程语言并非什么新鲜事物,早在面向对象编程语言成为主流之前,人们就已经使用动态编程语言来开发了.即使在 Java