首页 > 代码库 > 多线程(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 }
输出结果:
需要注意的是: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 }
输出结果:
创建任务集合并输出结果
如下代码:
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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。