多线程(4)Task
2018-06-18 04:12:31来源:未知 阅读 ()
使用线程池使得创建线程已经很简单了,但是使用线程池不支持线程的取消,完成和失败通知等交互操作,为了解决这些问题,.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 //方法2 15 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.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 }
输出结果:
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:注册时的密码强度
下一篇:获取http和ftp地址的图片
- 最详细的java多线程教程来了 2020-06-08
- 系统化学习多线程(一) 2020-06-08
- 聊聊 OAuth 2.0 的 token expire_in 使用 2020-06-08
- 为什么阿里巴巴Java开发手册中强制要求接口返回值不允许使用 2020-06-06
- 学习笔记之方法引用 2020-06-06
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash