多线程(4)Task
使用线程池使得创建线程已经很简单了,但是使用线程池不支持线程的取消,完成和失败通知等交互操作,为了解决这些问题,.net 4.0带来了TPL(Task Parallel Library)任务并行库,下面就来总结下Task的使用。
创建和运行任务
在.net 4.0下使用task创建一个线程非常简单,有两种方式,如下代码:

View Code
输出结果:

需要注意的是:task也是基于线程池的,所以这两个任务的执行顺序是不固定的。
取消任务
创建一个新的任务之后,我们随时都可以取消它,取消方法如下代码:

View Code输出结果:

创建任务集合并输出结果
如下代码:
1 namespace ConsoleApplication21
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //创建任务集合并输出结果
8 var tasks = new List<Task<string>>();
9
10 var task1 = Task.Factory.StartNew<string>(() =>
11 {
12 Console.WriteLine("task1 running on thread id:"+ Thread.CurrentThread.ManagedThreadId);
13 return "task1";
14 });
15 tasks.Add(task1);
16
17 var task2 = Task.Factory.StartNew<string>(() =>
18 {
19 Console.WriteLine("task2 running on thread id:" + Thread.CurrentThread.ManagedThreadId);
20 return "task2";
21 });
22 tasks.Add(task2);
23
24 var task3 = Task.Factory.StartNew<string>(() =>
25 {
26 Console.WriteLine("task3 running on thread id:" + Thread.CurrentThread.ManagedThreadId);
27 return "task3";
28 });
29 tasks.Add(task3);
30
31 //输出结果
32 foreach (var item in tasks)
33 {
34 Console.WriteLine(item.Result);//调用Task的Result方法相当于调用了Task.WaitAll(tasks.ToArray());
35 }
36
37 Console.ReadKey();
38 }
39 }
40 }
输出结果:

这里要注意2点:
1,每个任务会开启一个新的线程,并且运行顺序不固定。
2,Task.Result相当于调用了Wait方法,等待异步任务完成。
多任务的串行化
如下代码:
1 namespace ConsoleApplication22
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //多任务的串行化
8 var task1 = Task.Factory.StartNew(() =>
9 {
10 Console.WriteLine("start task1...");
11 Console.WriteLine("current thread id:"+ Thread.CurrentThread.ManagedThreadId);
12 });
13
14 var task2 = task1.ContinueWith((item) =>
15 {
16 Console.WriteLine("start task2...");
17 Console.WriteLine("current thread id:" + Thread.CurrentThread.ManagedThreadId);
18 });
19
20 var task3 = task2.ContinueWith((item)=>
21 {
22 Console.WriteLine("start task3...");
23 Console.WriteLine("current thread id:" + Thread.CurrentThread.ManagedThreadId);
24 });
25
26 Console.ReadKey();
27 }
28 }
29 }
输出结果:

注意,多任务串行化后,就相当于顺序执行了,而且有可能使用的是同一个线程,从上图的thread id就可以看出来。
多任务等待执行完成
如下代码:
1 namespace ConsoleApplication23
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //多任务等待执行完成
8 var tasks = new List<Task<string>>();
9
10 var task1 = Task.Factory.StartNew<string>(() =>
11 {
12 Console.WriteLine("task1");
13 return "task1";
14 });
15 tasks.Add(task1);
16
17 var task2 = Task.Factory.StartNew<string>(() =>
18 {
19 Console.WriteLine("task2");
20 return "task2";
21 });
22 tasks.Add(task2);
23
24 var task3 = Task.Factory.StartNew<string>(() =>
25 {
26 Console.WriteLine("task3");
27 return "task3";
28 });
29 tasks.Add(task3);
30
31 //等待所有任务完成
32 Task.WaitAll(tasks.ToArray());
33
34 //等价于下面的调用
35 //foreach (var item in tasks)
36 //{
37 // item.Result
38 //}
39
40 Console.ReadKey();
41 }
42 }
43 }
输出结果:

需要注意的是,如果是有返回值的task,可以使用Task.Result获取返回值的同时,也在等待Task执行完成,相当于调用了Task.Wait方法。
创建子任务
如下代码:
1 namespace ConsoleApplication24
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 //创建子任务
8 var parentTask = Task.Factory.StartNew(() =>
9 {
10 Console.WriteLine("parent task!");
11 var childTask = Task.Factory.StartNew(() =>
12 {
13 Console.WriteLine("child task!");
14 }, TaskCreationOptions.AttachedToParent);
15 });
16
17 Console.ReadKey();
18 }
19 }
20 }
输出结果:

漫思

浙公网安备 33010602011771号