我們知道,每個應用程序就是一個進程,一個進程有多個線程。Task Parallel Library為我們的異步編程、多線程編程提供了強有力的支持,它允許一個主線程運行的同時,另外的一些線程或Task也同時運行。本篇體驗基本用法。
基本用法
Taks的構造函數接收的類型是Action,也就是一個委托。
static void Main(string[] args){var t1 = new Task(() =>{Console.WriteLine("任務1開始");Thread.Sleep(1000);Console.WriteLine("任務1結束");});t1.Start();Console.ReadKey();}
如果把方法放到外面。
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同時執行。
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工廠。
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方法。
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方法。
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,需要為方法帶上CancellationToken類型參數。
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從獲取方法的返回結果呢?
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;}
后面一個Task獲取前面一個Task的返回值。
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();}
等待所有Task完成。
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。
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方法。
static void Main(string[] args){Task.Factory.StartNew(() => SaySth("hello"));Console.ReadKey();}static void SaySth(string msg){Console.WriteLine(msg);}
2、通過Task的Start實例方法
static void Main(string[] args){var t = new Task(() => SaySth("hello"));t.Start();Console.ReadKey();}
或者干脆用委托。
static void Main(string[] args){Task t = new Task(delegate {SaySth("hello");});t.Start();Console.ReadKey();}
3、Task的靜態方法Run
static void Main(string[] args){Task t = Task.Run(() => SaySth("hello"));Console.ReadKey();}static void SaySth(string msg){Console.WriteLine(msg);}
一個例子
比如說要下載某個頁面,在保持當前UI界面無影響的情況下,使用Task在后臺啟動任務下載某個頁面。
static void Main(string[] args){Console.WriteLine("界面內容");Task<string> r = DownloadAsync("http://www.baidu.com");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));}
新聞熱點
疑難解答