文章目錄
- 前言
- 一、Task 的基本概念
- 二、創建 Task
- 使用異步方法
- 使用 Task.Run 方法
- 三、等待 Task 完成
- 使用 await 關鍵字
- 使用 Task.Wait 方法
- 四、處理 Task 的異常
- 使用 try-catch 塊
- 使用 Task.Exception 屬性
- 五、Task 的延續
- 使用 ContinueWith 方法
- 使用 await 關鍵字和異步方法
- 六、Task 的并行執行
- 使用多個 Task
- 使用 Task.WhenAll 方法
- 七、總結
前言
??在 C# 中,Task代表一個異步操作。它允許你在不阻塞主線程的情況下執行耗時的操作,從而提高應用程序的響應性和性能。本教程將詳細介紹 C# 中的Task。
一、Task 的基本概念
??Task是.NET Framework 4.0 引入的一種異步編程模型,它代表一個可能尚未完成的操作。Task可以表示任何異步操作,例如文件讀取、網絡請求、數據庫查詢等。與傳統的異步編程模型相比,Task提供了一種更加簡潔和高效的方式來處理異步操作。
二、創建 Task
使用異步方法
??C# 中的異步方法通常以async關鍵字開頭,并返回一個Task或Task。例如:
async Task<int> CalculateSumAsync(){int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;}
??在這個例子中,CalculateSumAsync方法是一個異步方法,它返回一個Task,表示一個異步操作,該操作將計算從 0 到 99 的整數之和,并返回結果。
使用 Task.Run 方法
??Task.Run方法可以將一個委托作為參數,并在一個新的線程上執行該委托。例如:
Task<int> task = Task.Run(() =>{int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;});
??在這個例子中,Task.Run方法將一個 lambda 表達式作為參數,該表達式計算從 0 到 99 的整數之和,并返回結果。Task.Run方法返回一個Task,表示在新線程上執行的異步操作。
三、等待 Task 完成
使用 await 關鍵字
??await關鍵字用于等待一個Task完成。當使用await關鍵字等待一個Task時,當前方法會暫停執行,直到Task完成。例如:
async Task<int> CalculateSumAsync(){int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;}async Task Main(){int result = await CalculateSumAsync();Console.WriteLine(result);}
??在這個例子中,Main方法是一個異步方法,它調用CalculateSumAsync方法,并使用await關鍵字等待該方法完成。一旦CalculateSumAsync方法完成,result變量將被賦值為該方法的返回值,并在控制臺上輸出結果。
使用 Task.Wait 方法
??Task.Wait方法用于等待一個Task完成。與await關鍵字不同,Task.Wait方法會阻塞當前線程,直到Task完成。例如:
Task<int> task = Task.Run(() =>{int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;});task.Wait();int result = task.Result;Console.WriteLine(result);
??在這個例子中,task.Wait()方法會阻塞當前線程,直到task完成。一旦task完成,result變量將被賦值為task的返回值,并在控制臺上輸出結果。
四、處理 Task 的異常
使用 try-catch 塊
??當等待一個Task時,可以使用try-catch塊來捕獲Task中發生的異常。例如:
async Task<int> CalculateSumAsync(){int sum = 0;for (int i = 0; i < 100; i++){sum += i;}throw new Exception("An error occurred.");return sum;}async Task Main(){try{int result = await CalculateSumAsync();Console.WriteLine(result);}catch (Exception ex){Console.WriteLine(ex.Message);}}
??在這個例子中,CalculateSumAsync方法在計算總和的過程中拋出了一個異常。在Main方法中,使用try-catch塊來捕獲這個異常,并在控制臺上輸出異常消息。
使用 Task.Exception 屬性
??Task.Exception屬性返回一個AggregateException,其中包含了Task中發生的所有異常。例如:
Task<int> task = Task.Run(() =>{int sum = 0;for (int i = 0; i < 100; i++){sum += i;}throw new Exception("An error occurred.");return sum;});try{task.Wait();int result = task.Result;Console.WriteLine(result);}catch (AggregateException ex){foreach (var innerException in ex.InnerExceptions){Console.WriteLine(innerException.Message);}}
??在這個例子中,task.Wait()方法會阻塞當前線程,直到task完成。如果task中發生了異常,catch塊將捕獲AggregateException,并遍歷其中的所有異常,在控制臺上輸出異常消息。
五、Task 的延續
使用 ContinueWith 方法
??ContinueWith方法用于在一個Task完成后執行另一個操作。例如:
Task<int> task = Task.Run(() =>{int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;});task.ContinueWith(t =>{Console.WriteLine(t.Result);});
??在這個例子中,task.ContinueWith方法在task完成后執行一個 lambda 表達式,該表達式輸出task的結果。
使用 await 關鍵字和異步方法
??也可以使用await關鍵字和異步方法來實現Task的延續。例如:
async Task<int> CalculateSumAsync(){int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;}async Task PrintResultAsync(int result){Console.WriteLine(result);}async Task Main(){int result = await CalculateSumAsync();await PrintResultAsync(result);}
??在這個例子中,Main方法首先調用CalculateSumAsync方法,并使用await關鍵字等待該方法完成。然后,它調用PrintResultAsync方法,并使用await關鍵字等待該方法完成。這樣,PrintResultAsync方法就作為CalculateSumAsync方法的延續執行。
六、Task 的并行執行
使用多個 Task
??可以同時啟動多個Task,并等待它們全部完成。例如:
Task<int> task1 = Task.Run(() =>{int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;});Task<int> task2 = Task.Run(() =>{int product = 1;for (int i = 1; i <= 10; i++){product *= i;}return product;});Task.WaitAll(task1, task2);int sum = task1.Result;int product = task2.Result;Console.WriteLine(sum);Console.WriteLine(product);
??在這個例子中,同時啟動了兩個Task,一個計算從 0 到 99 的整數之和,另一個計算從 1 到 10 的整數之積。然后,使用Task.WaitAll方法等待這兩個Task全部完成,并輸出結果。
使用 Task.WhenAll 方法
??Task.WhenAll方法返回一個Task,當所有傳入的Task都完成時,這個Task才完成。例如:
Task<int> task1 = Task.Run(() =>{int sum = 0;for (int i = 0; i < 100; i++){sum += i;}return sum;});Task<int> task2 = Task.Run(() =>{int product = 1;for (int i = 1; i <= 10; i++){product *= i;}return product;});Task<int[]> tasks = Task.WhenAll(task1, task2);int[] results = await tasks;int sum = results[0];int product = results[1];Console.WriteLine(sum);Console.WriteLine(product);
??在這個例子中,使用Task.WhenAll方法等待兩個Task全部完成,并返回一個包含兩個Task結果的數組。然后,使用await關鍵字等待這個Task完成,并輸出結果。
七、總結
??Task是 C# 中一種強大的異步編程模型,它允許你在不阻塞主線程的情況下執行耗時的操作。通過使用Task,你可以提高應用程序的響應性和性能,同時保持代碼的簡潔和可讀性。