.NET 4并行编程入门之Task基础

开发 后端
本文将介绍的是.NET 4并行编程入门,包括Task方面的基础以及Task的创建信息和获得Task的执行结果。希望对大家有所帮助。

查看本系列其他文章,请参看

[[11656]]

本篇文章的议题如下:

1.Task基础介绍

2.Task的创建

3.获取Task的执行结果

4. 补充细节

1.Task基础介绍

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

这里展示的只是一段简单的代码,不能显示出并行编程的特点。但是我们还是从最基本的开始看,慢慢进入深一点的话题。

如果你曾经用过.NET 中的多线程编程,比较一下,就会发现:这段代码虽然在底层还是使用了多线程,但是写法上却简化了很多,一行代码就实现了一个并行编程。

下面我们就从Task类开始谈。

Task类是Task Programming Library(TPL)中最核心的一个类,下面我将会像大家展示如何使用一些方法来创建不同类型的Task,

取消Task,等待Task执行完成,获取Task执行后的结果和对异常进行处理。

在开始讨论之前,我们首先快速的看看之前的代码:

这个命名空间将会是我们之后在讲述并行编程经常使用的一个。这个空间包含了很多与并行编程有关的类。

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

上面代码中,最主要的代码如下:

  1.   Task.Factory.StartNew(() =>  
  2. {  
  3. Console.WriteLine("Hello World");  
  4. }); 

我们用静态方法: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交给底下的线程去执行。

下面就看看代码:

代码

  1. using System;  
  2. using System.Threading.Tasks;  
  3. namespace Listing_02  
  4. {  
  5. class Listing_02  
  6. {  
  7. static void Main(string[] args)  
  8. {  
  9.  
  10. // use an Action delegate and a named method  
  11. Task task1 = new Task(new Action(printMessage));  
  12. // use a anonymous delegate  
  13. Task task2 = new Task(delegate 
  14. {  
  15. printMessage();  
  16. });  
  17.  
  18. // use a lambda expression and a named method  
  19. Task task3 = new Task(() => printMessage());  
  20. // use a lambda expression and an anonymous method  
  21. Task task4 = new Task(() =>  
  22. {  
  23. printMessage();  
  24. });  
  25.  
  26. task1.Start();  
  27. task2.Start();  
  28. task3.Start();  
  29. task4.Start();  
  30. // wait for input before exiting  
  31. Console.WriteLine("Main method complete. Press enter to finish.");  
  32. Console.ReadLine();  
  33. }  
  34.  
  35. static void printMessage()  
  36. {  
  37. Console.WriteLine("Hello World");  
  38. }}} 

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

2.1 为创建的Task传入参数  

  

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

代码

  1. using System;  
  2. using System.Threading.Tasks;  
  3. namespace Listing_04  
  4. {  
  5. class Listing_04  
  6. {  
  7. static void Main(string[] args)  
  8. {  
  9. string[] messages = { "First task""Second task",  
  10. "Third task""Fourth task" };  
  11. foreach (string msg in messages)  
  12. {  
  13. Task myTask = new Task(obj => printMessage((string)obj), msg);  
  14. myTask.Start();  
  15. }  
  16. // wait for input before exiting  
  17. Console.WriteLine("Main method complete. Press enter to finish.");  
  18. Console.ReadLine();  
  19. }  
  20.  
  21. static void printMessage(string message)  
  22. {  
  23. Console.WriteLine("Message: {0}", message);  
  24. }}} 

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

想向Task传入参素,只能用System.Action<object>

3.获取Task的执行结果

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

代码显示如下:

代码 

  1.  static void Main(string[] args)  
  2. {  
  3. // create the task  
  4. Task<int> task1 = new Task<int>(() =>  
  5. {  
  6. int sum = 0;  
  7. for (int i = 0; i < 100; i++)  
  8. {  
  9. sum += i;  
  10. }  
  11. return sum;  
  12. });  
  13.  
  14. task1.Start();  
  15. // write out the result  
  16. Console.WriteLine("Result 1: {0}", task1.Result);  
  17.  
  18. Console.ReadLine();  

只有在task执行完成之后,才能获取到Result的值。

下面的代码展示了如何通过Task.Factory.StartNew<T>()创建一个Task,并且获取结果:

代码 

  1. static void Main(string[] args)  
  2. {  
  3. // create the task  
  4. Task<int> task1 = Task.Factory.StartNew<int>(() =>  
  5. {  
  6. int sum = 0;  
  7. for (int i = 0; i < 100; i++)  
  8. {  
  9. sum += i;  
  10. }  
  11. return sum;  
  12. });  
  13.  
  14. // write out the result  
  15. Console.WriteLine("Result 1: {0}", task1.Result);  
  16. 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的一些区别,因为我认为它们的设计思想很相近)

原文标题:.NET 4 并行(多核)编程系列之二

链接:http://www.cnblogs.com/Leo_wl/archive/2010/05/31/1747931.html

【编辑推荐】

  1. 微软发布新版Windows 7及.NET 4软件开发工具包
  2. 详解.NET 4.0并行计算支持历史
  3. 详读.NET 4.0环境配置
  4. 详解.NET 4.0中异常处理方面的新特性
  5. 三方面诠释.NET 4.0的新特性
责任编辑:彭凡 来源: 博客园
相关推荐

2010-06-08 08:41:08

.NET 4并行编程

2010-06-07 08:43:46

.NET 4并行编程

2010-06-09 09:18:34

.NET 4并行编程

2010-06-11 09:01:02

.NET 4并行编程

2010-06-02 08:53:51

.NET 4并行编程

2011-03-24 09:23:43

.NET 4多核并行

2010-06-24 09:12:27

.NET 4并行编程

2024-09-29 16:22:18

多线程TaskC#

2024-09-27 19:42:09

工具C#Task​

2015-10-13 09:18:00

.Net编程教程

2009-07-24 15:41:00

ASP.NET编程入门

2024-04-07 09:04:18

Parallel 类编程工具.NET

2010-04-21 09:23:09

.NET 4

2011-09-27 13:52:41

2011-07-05 17:19:47

元编程

2010-01-07 09:53:09

Winform多线程编

2011-08-10 17:04:43

JavaScript

2009-08-03 15:53:11

ASP.NET移动开发

2024-06-04 15:56:48

Task​.NET异步编程

2011-07-11 09:29:32

PHP面向对象编程
点赞
收藏

51CTO技术栈公众号