C# 之 異步多執行緒任務相關以及概念使用介紹
- 一,相關關鍵字和運算子
- 1.1 Async/Await 介紹和使用示例
- 1.2 Async/Await 異步編程中的最佳做法
- 二, Task 類
- 2.1 Task定義
- 2.2 屬性方法
- 1.3 Task使用
- 三,TaskCompletionSource 類
- 3.1 概念定義
- 3.2 屬性函式
- 3.3 模擬情景
一,相關關鍵字和運算子
1.1 Async/Await 介紹和使用示例
-
關鍵字 Async
使用 ‘async’ 修飾符可將方法、lambda 運算式或匿名方法指定為異步, 如果對方法或運算式使用此修飾符,則其稱為異步方法 ,‘async’ 關鍵字是背景關系關鍵字,原因在于只有當它修飾方法、lambda 運算式或匿名方法時,它才是關鍵字,
如果 ‘async’ 關鍵字修改的方法不包含 ‘await’ 運算式或陳述句,則該方法將同步執行, 編譯器警告將通知你不包含 ‘await’ 陳述句的任何異步方法,因為該情況可能表示存在錯誤,
定義異步方法:
public async Task<string> AsyncTest()
{
}
-
運算子 Await
‘await’ 運算子暫停對其所屬的 ‘async’ 方法的求值,直到其運算元表示的異步操作完成, 異步操作完成后,如果有回傳值 ‘await’ 運算子將回傳操, 當 ‘await’ 運算子應用到表示已完成操作的運算元時,它將立即回傳操作的結果,而不會暫停其所屬的方法, ‘await’ 運算子不會阻止計算異步方法的執行緒, 當 ‘await’ 運算子暫停其所屬的異步方法時,控制元件將回傳到方法的呼叫方法,
使用Await運算子:
public async Task<string> AsyncTest()
{
// 等AsyncTest_1 執行完成
await AsyncTest_1();
}
public async Task<string> AsyncTest_1()
{
return "任務AsyncTest_1 執行完成";
}
1.2 Async/Await 異步編程中的最佳做法
此部分(1.3)取自 --> MSDN

二, Task 類
2.1 Task定義
Task類表示不回傳值并且通常以異步方式執行的單個操作, Task 物件是在 .NET Framework 4 中首次引入的 基于任務的異步模式 的中心組件之一, 由于物件執行的作業 Task 通常在執行緒池執行緒上異步執行,而不是在主應用程式執行緒上同步執行,因此可以使用 Status 屬性以及 IsCanceled 、 IsCompleted 和 IsFaulted 屬性來確定任務的狀態, 通常,lambda 運算式用于指定任務要執行的作業,
2.2 屬性方法
屬性串列:
| 屬性名 | 說明 |
|---|---|
| AsyncState | 獲取在創建 Task 時提供的狀態物件,如果未提供,則為 null,(只讀) |
| CompletedTask | 此屬性將回傳其 Status 屬性設定為的任務 RanToCompletion , 若要創建一個回傳值并運行到完成的任務,請呼叫 FromResult 方法,(只讀) |
| CreationOptions | 獲取用于創建此任務的 TaskCreationOptions,(只讀) |
| CurrentId | 回傳當前正在執行 Task 的 ID,(只讀) |
| Exception | 獲取導致 AggregateException 提前結束的 Task, 如果 Task 成功完成或尚未引發任何例外,這將回傳 null,(只讀) |
| Factory | 一個工廠物件,可創建多種 Task 和 Task<TResult> 物件,提供對用于創建和配置 Task 和 Task 實體的工廠方法的訪問, |
| Id | 任務 Id 按需分配,不一定表示任務實體的創建順序,有可能存在沖突,若要從任務正在執行的代碼內獲取當前正在執行的任務的任務 ID,請使用 CurrentId 屬性, |
| IsCanceled | 如果任務由于被取消而完成,則為 true;否則為 false, |
| IsCompleted | true 如果任務已完成 (即,任務處于以下三個最終狀態之一: RanToCompletion 、 Faulted 或 Canceled) ,則為; 否則為 false , |
| IsCompletedSuccessfully | true 如果任務運行到完成,則為;否則為 false , |
| IsFaulted | 如果任務引發了未經處理的例外,則為 true;否則為 false, |
| Status | 此任務實體的當前 TaskStatus, |
方法串列:
| 方法名 | 方法說明 |
|---|---|
| ConfigureAwait(bool) | 引數:嘗試將延續任務封送回背景關系,則為 true;否則為 false, 回傳值:嘗試將延續任務封送回原始背景關系,則為 true;否則為 false, |
| ContinueWith() | 創建一個在目標 Task 完成時異步執行的延續任務,即完成一個任務開啟下一個任務, |
| Delay() | 創建將在時間延遲后完成的任務,在完成回傳的任務前要等待的引數毫秒數;如果無限期等待,則為 -1, |
| Dispose() | 釋放 Task 類的當前實體所使用的所有資源, |
| FromCanceled() | 創建 Task 或者 Task<TResult>,它因指定的取消標記進行的取消操作而完成, |
| FromException() | 創建 Task 或者 Task<TResult>,它在完成后出現指定的例外, |
| FromResult(TResult) | 型別引數: TResult 任務回傳的結果的型別,引數 TResult 存盤入已完成任務的結果,回傳值: Task<TResult>已成功完成的任務, |
| GetAwaiter() | 獲取用于等待此 Task 的 awaiter,回傳:一個 awaiter 實體, |
| Run() | 將在執行緒池上運行的指定作業排隊,并回傳該作業的任務或 Task<TResult> 句柄, |
| RunSynchronously() | 對當前的 Task 同步運行 TaskScheduler, |
| Start() | 啟動 Task,并將它安排到當前的 TaskScheduler 中執行, |
| Wait() | 等待當前 ‘Task’ 完成執行程序, |
| WaitAll() | 等待所有提供的 Task 物件完成執行程序, |
| WaitAny() | 等待提供的任一 Task 物件完成執行程序, |
| WhenAll() | 所有提供的任務已完成時,創建將完成的任務, |
| WhenAny() | 任何提供的任務已完成時,創建將完成的任務, |
| Yield() | 創建異步產生當前背景關系的等待任務,可以 await Task.Yield(); 在異步方法中使用來強制異步完成方法, |
1.3 Task使用
Task最厲害的地方就是他的任務控制了,你可以很好的控制task的執行順序,讓多個task有序的作業,
任務跟執行緒不是一對一的關系,比如開10個任務并不是說會開10個執行緒,這一點任務有點類似執行緒池,但是任務相比執行緒池有很小的開銷和精確的控制,
一個最簡單的示例: 開啟任務1 --> 呼叫并等待任務2完成 --> 繼續執行任務1
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskTest
{
class Program
{
static void Main(string[] args)
{
Task<string> result = task_1();
Console.WriteLine(result.Result);
Console.ReadKey();
}
static async Task<string> task_1()
{
Console.WriteLine("任務1 開始執行");
Console.WriteLine("等待任務2 執行完成... ");
string res = await task_2();
Console.WriteLine("任務2 執行完成... 回傳值: " + res);
return "任務1執行完成回傳值";
}
static async Task<string> task_2()
{
Thread.Sleep(1000);
return "任務2執行完成";
}
}
}
執行結果:

三,TaskCompletionSource 類
3.1 概念定義
TaskCompletionSource :表示未系結到委托的 Task 的制造者方,并通過 Task 屬性提供對使用者方的訪問,
通常情況下, Task 需要表示另一個異步操作, TaskCompletionSource 提供此目的, 它允許創建可以向使用者傳遞的任務,而這些使用者可以使用任務的成員,就像對待任何其他成員一樣, 但是,與大多數任務不同,由創建的任務的狀態由 TaskCompletionSource 中的方法顯式控制 TaskCompletionSource , 這使得外部異步操作能夠傳播到基礎 Task, 分隔還可確保使用者不能在不訪問相應的的情況下轉換狀態 TaskCompletionSource,所有成員 TaskCompletionSource 都是執行緒安全的,可同時從多個執行緒使用,
3.2 屬性函式
屬性:
- Task :獲取由此 ‘Task’ 創建的 ‘TaskCompletionSource’,
此屬性使使用者可以訪問由此 ‘Task’ 實體控制的, ‘SetResult()’ ‘SetException(Exception)’ ‘SetException(IEnumerable)’ 此實體上的 和 ‘SetCanceled()’ 方法 (及其 Try 變體) 都將導致相關狀態在此基礎上轉換 Task ,
建構式:
| 函式 | 說明 |
|---|---|
| TaskCompletionSource() | 創建一個 ‘TaskCompletionSource’, |
| TaskCompletionSource(Object) | 使用指定的狀態創建一個 ‘TaskCompletionSource’, |
| TaskCompletionSource(Object, TaskCreationOptions) | 使用指定的狀態和選項創建一個 ‘TaskCompletionSource’,'Task’通過此實體創建并可通過其屬性訪問的將 ‘Task’ 使用指定的實體化 ‘creationOptions’, |
| TaskCompletionSource(TaskCreationOptions) | 使用指定的選項創建一個 ‘TaskCompletionSource’, |
函式:
PS:基礎 Task 已處于以下三種最終狀態的其中一種:RanToCompletion、Faulted 或 Canceled,
| 函式名 | 說明 |
|---|---|
| SetCanceled() | 將基礎 ‘Task’ 轉換為 ‘Canceled’ 狀態, |
| SetCanceled(CancellationToken) | 使用指定的標記將基礎 ‘Task’ 轉換為 ‘Canceled’ 狀態, |
| SetException(Exception) | 將基礎 ‘Task’ 轉換為 ‘Faulted’ 狀態, |
| SetException(IEnumerable) | 將基礎 ‘Task’ 轉換為 ‘Faulted’ 狀態, |
| SetResult() | 將基礎 ‘Task’ 轉換為 ‘RanToCompletion’ 狀態, |
| TrySetCanceled() | 嘗試將基礎 ‘Task’ 轉換為 ‘Canceled’ 狀態, |
| TrySetCanceled(CancellationToken) | 嘗試將基礎 ‘Task’ 轉換為 ‘Canceled’ 狀態, |
| TrySetException(Exception) | 嘗試將基礎 ‘Task’ 轉換為 ‘Faulted’ 狀態, |
| TrySetException(IEnumerable) | 嘗試將基礎 ‘Task’ 轉換為 ‘Faulted’ 狀態, |
| TrySetResult() | 嘗試將基礎 ‘Task’ 轉換為 ‘RanToCompletion’ 狀態, |
3.3 模擬情景
用戶操作:
- 用戶點擊商品 --> 選擇支付平臺 --> 等待選擇完成 --> 執行支付邏輯
代碼邏輯:
- 呼叫支付任務 --> 等待用戶選擇 --> 回傳用戶所選 --> 執行支付邏輯
using System;
using System.Threading.Tasks;
namespace VSProject
{
class Program
{
static TaskCompletionSource<string> ts;
static void Main(string[] args)
{
// 開啟異步任務
TaskTest_1();
while (true)
{
ConsoleKeyInfo info = Console.ReadKey(true);
switch (info.Key)
{
case ConsoleKey.S:
Console.WriteLine("用戶輸入S鍵,模擬任務成功");
Success();
break;
case ConsoleKey.F:
Console.WriteLine("用戶輸入F鍵,模擬任務成功");
Fail();
break;
}
}
Console.ReadLine();
}
/// <summary>
/// 異步任務
/// </summary>
/// <returns></returns>
static async Task TaskTest_1()
{
Console.WriteLine("TaskTest_1 任務開始...");
ts = new TaskCompletionSource<string>();
string res;
try
{
res = await ts.Task;
}
catch (Exception e)
{
Console.WriteLine("等待任務例外...");
throw e;
}
Console.WriteLine("TaskTest_1 任務結束... 傳值為:" + res);
}
/// <summary>
/// 任務成功
/// </summary>
static void Success()
{
if (ts.Task.IsCompleted) return;
ts.SetResult("模擬任務完成傳值");
}
/// <summary>
/// 任務取消或失敗
/// </summary>
static void Fail()
{
if (ts.Task.IsCompleted) return;
ts.SetException(new Exception("任務取消或失敗"));
}
}
}
用戶按下S鍵,模擬成功:

用戶按下F鍵,模擬失敗:

相關鏈接:
MSDN - Task 類
MSDN - TaskCompletionSource 類
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/303612.html
標籤:其他
