我们知道,每个应用程序就是一个进程,一个进程有多个线程。Task Parallel Library为我们的异步编程、多线程编程提供了强有力的支持,它允许一个主线程运行的同时,另外的一些线程或Task也同时运行。本篇体验基本用法。
基本用法
Taks的构造函数接收的类型是Action,也就是一个委托。
1 2 3 4 5 6 7 8 9 10 11 | static void Main( string [] args) { var t1 = new Task(() => { Console.WriteLine( "任务1开始" ); Thread.Sleep(1000); Console.WriteLine( "任务1结束" ); }); t1.Start(); Console.ReadKey(); } |
如果把方法放到外面。
1 2 3 4 5 6 7 8 9 10 11 12 | static void Main( string [] args) { var t1 = new Task(() => DoSth(1,2000)); t1.Start(); Console.ReadKey(); } static void DoSth( int id, int sleepTime) { Console.WriteLine( "任务{0}开始" ,id); Thread.Sleep(sleepTime); Console.WriteLine( "任务{0}结束" ,id); } |
如果有多个Task同时执行。
1 2 3 4 5 6 7 8 9 10 | static void Main( string [] args) { var t1 = new Task(() => DoSth(1,2000)); t1.Start(); var t2 = new Task(() => DoSth(2, 1500)); t2.Start(); var t3 = new Task(() => DoSth(3, 3000)); t3.Start(); Console.ReadKey(); } |
如果有很多Task,每个Task手动启动的话很费事,Task Parallel Library为我们准备了Task工厂。
1 2 3 4 5 6 7 | static void Main( string [] args) { var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)); var t2 = Task.Factory.StartNew(() => DoSth(2, 1500)); var t3 = Task.Factory.StartNew(() => DoSth(3, 3000)); Console.ReadKey(); } |
如果我们想在一个任务结束之后立即执行某个任务,可以使用ContinueWith方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | static void Main( string [] args) { var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)).ContinueWith((pre)=> DoOtherThing(4,2000)); var t2 = Task.Factory.StartNew(() => DoSth(2, 1500)); var t3 = Task.Factory.StartNew(() => DoSth(3, 3000)); Console.ReadKey(); } static void DoSth( int id, int sleepTime) { Console.WriteLine( "任务{0}开始" ,id); Thread.Sleep(sleepTime); Console.WriteLine( "任务{0}结束" ,id); } static void DoOtherThing( int id, int sleepTime) { Console.WriteLine( "其他任务{0}开始" , id); Thread.Sleep(sleepTime); Console.WriteLine( "其他任务{0}结束" , id); } |
如果希望等待所有的Task执行完毕,使用WaitAll方法。
1 2 3 4 5 6 7 8 9 10 | static void Main( string [] args) { var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)); var t2 = Task.Factory.StartNew(() => DoSth(2, 1500)); var t3 = Task.Factory.StartNew(() => DoSth(3, 3000)); var taskList = new List<task> {t1, t2, t3}; Task.WaitAll(taskList.ToArray()); Console.WriteLine( "我是在所有Task执行完毕后才执行的" ); Console.ReadKey(); }</task> |
如果想手动取消结束某个Task,需要为方法带上CancellationToken类型参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | static void Main( string [] args) { var source = new CancellationTokenSource(); try { var t1 = Task.Factory.StartNew(() => DoSth(1, 1000, source.Token)) .ContinueWith((pre) => DoOtherThing(2, 2000)); source.Cancel(); } catch (Exception ex) { Console.WriteLine(ex.GetType()); } Console.WriteLine( "haha" ); Console.ReadKey(); } static void DoSth( int id, int sleepTime, CancellationToken token) { if (token.IsCancellationRequested) { Console.WriteLine( "任务被取消" ); token.ThrowIfCancellationRequested(); } Console.WriteLine( "任务{0}开始" ,id); Thread.Sleep(sleepTime); Console.WriteLine( "任务{0}结束" ,id); } static void DoOtherThing( int id, int sleepTime) { Console.WriteLine( "其他任务{0}开始" , id); Thread.Sleep(sleepTime); Console.WriteLine( "其他任务{0}结束" , id); } |
如何从Task从获取方法的返回结果呢?
1 2 3 4 5 6 7 8 9 10 11 12 | static void Main( string [] args) { Console.WriteLine( "开始计算" ); Task< int > t = Task.Factory.StartNew(() => Sum(1, 2)); Console.WriteLine( "等待结果" ); Console.WriteLine(t.Result); Console.ReadKey(); } static int Sum( int a, int b) { return a + b; }</ int > |
后面一个Task获取前面一个Task的返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | static void Main( string [] args) { Task< string > firstTask = Task.Factory.StartNew< string >(() => { Console.WriteLine( "第一个任务开始" ); return "hi from the one" ; }); Task secondTask = firstTask.ContinueWith((prevoursTask) => { Console.WriteLine( "这里是第二个任务,获取到第一个任务的返回值是{0}" ,prevoursTask.Result,TaskContinuationOptions.OnlyOnRanToCompletion); }); secondTask.Wait(); Console.ReadKey(); }</ string ></ string > |
等待所有Task完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | static void Main( string [] args) { var t1 = Task.Factory.StartNew(() => { Console.WriteLine( "第一个任务" ); Thread.Sleep(1000); }); var t2 = Task.Factory.StartNew(() => { Console.WriteLine( "第二个任务" ); Thread.Sleep(1000); }); var taskList = new List<task> {t1, t2}; Task.Factory.ContinueWhenAll(taskList.ToArray(), (t) => { Console.WriteLine( "所有任务完成我就出来" ); }); Console.ReadKey(); }</task> |
如果是嵌套Task。
1 2 3 4 5 6 7 8 9 10 11 | static void Main( string [] args) { Task.Factory.StartNew(() => { Task child = Task.Factory.StartNew(() => { Console.WriteLine( "我是子任务" ); }, TaskCreationOptions.AttachedToParent); }).Wait(); Console.ReadKey(); } |
启动Task的几种方式
1、通过Task.Factory.StartNew方法。
1 2 3 4 5 6 7 8 9 | static void Main( string [] args) { Task.Factory.StartNew(() => SaySth( "hello" )); Console.ReadKey(); } static void SaySth( string msg) { Console.WriteLine(msg); } |
2、通过Task的Start实例方法
1 2 3 4 5 6 | static void Main( string [] args) { var t = new Task(() => SaySth( "hello" )); t.Start(); Console.ReadKey(); } |
或者干脆用委托。
1 2 3 4 5 6 | static void Main( string [] args) { Task t = new Task( delegate {SaySth( "hello" );}); t.Start(); Console.ReadKey(); } |
3、Task的静态方法Run
1 2 3 4 5 6 7 8 9 | static void Main( string [] args) { Task t = Task.Run(() => SaySth( "hello" )); Console.ReadKey(); } static void SaySth( string msg) { Console.WriteLine(msg); } |
一个例子
比如说要下载某个页面,在保持当前UI界面无影响的情况下,使用Task在后台启动任务下载某个页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | static void Main( string [] args) { Console.WriteLine( "界面内容" ); while (!r.IsCompleted) { Console.Write( "." ); Thread.Sleep(250); } Console.WriteLine(r.Result); Console.ReadKey(); } private static string DownloadWebPage( string url) { WebRequest request = WebRequest.Create(url); WebResponse response = request.GetResponse(); var reader = new StreamReader(response.GetResponseStream()); return reader.ReadToEnd(); } private static Task< string > DownloadAsync( string url) { return Task.Factory.StartNew(() => DownloadWebPage(url)); }</ string ></ string > |
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对IT俱乐部的支持。如果你想了解更多相关内容请查看下面相关链接