首页 > 代码库 > 多线程(4)Task

多线程(4)Task

 

  使用线程池使得创建线程已经很简单了,但是使用线程池不支持线程的取消,完成和失败通知等交互操作,为了解决这些问题,.net 4.0带来了TPL(Task Parallel Library)任务并行库,下面就来总结下Task的使用。

创建和运行任务

在.net 4.0下使用task创建一个线程非常简单,有两种方式,如下代码:

技术分享

技术分享
 1 namespace ConsoleApplication19 2 { 3     class Program 4     { 5         static void Main(string[] args) 6         { 7             //方法1 8             var task1 = new Task(() =>  9             {10                 Console.WriteLine("Create and start task!");11             });12             task1.Start();13 14             //方法215             Task.Factory.StartNew(() => 16             {17                 Console.WriteLine("Task factory start new task!");18             });19 20             Console.ReadKey();21         }22     }23 }
View Code

 

输出结果:

技术分享

需要注意的是:task也是基于线程池的,所以这两个任务的执行顺序是不固定的。 

取消任务

 创建一个新的任务之后,我们随时都可以取消它,取消方法如下代码:

技术分享

 

 

技术分享
 1 namespace ConsoleApplication20 2 { 3     class Program 4     { 5         static void Main(string[] args) 6         { 7             Console.WriteLine("Main thread starting..."); 8  9             var cts = new CancellationTokenSource();10             var task1 = Task.Factory.StartNew(() =>11             {12                 TaskAction(cts.Token);13             });14 15             Thread.Sleep(3000);16             Console.WriteLine(string.Format("current task status::{0}", task1.Status));17 18             //取消任务19             cts.Cancel();20             Console.WriteLine("start cancel task!");21             for (int i = 0; i < 5; i++)22             {23                 Thread.Sleep(500);24                 Console.WriteLine(string.Format("current task status::{0}", task1.Status));25             }26 27             Console.WriteLine("Main thread completed!");28             Console.ReadKey();29         }30 31         public static void TaskAction(CancellationToken token)32         {33             Console.WriteLine("Sub thread starting...");34 35             while (true)36             {37                 Thread.Sleep(1000);38                 if (token.IsCancellationRequested)39                 {40                     Console.WriteLine("Sub thread be cancelled!");41                     return;42                 }43                 Console.WriteLine("Sub thread is running!");44             }45         }46 47     }48 }
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.Result38             //}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 }

 

输出结果:

技术分享

 

多线程(4)Task