多线程-Task、await/async
Task是.netframwork4.0重新分裝的多線程類。原因以前的多線程(thread threadpool)不好用。(.net framwork也是的發展的,現在的EF,剛開始是一個edmx文件,現在的code first,ef輕量級。但是其他有的技術也是死掉了)
Task具有線程執行的可控性,返回值,代碼書寫簡單,性能好等特點。
Task創建主要有三種方式
1、Task參數
Task t = new Task(() => {for (int i = 0; i < 10; i++){Console.WriteLine(i);} }); t.Start(); View CodeAction,Action<object>,object?state,CancellationToken,TaskCreationOptions
Action<object>:task創建有參數的任務,參數只能是object
object:帶有參數委托的參數。
CancellationToken:線程取消通知
TaskCreationOptions:控制Task的執行方式
// // 摘要: // 指定可控制任務的創建和執行的可選行為的標志。 [Flags] public enum TaskCreationOptions {//// 摘要:// 指定應使用默認行為。None = 0,//// 摘要:// 提示 System.Threading.Tasks.TaskScheduler 以一種盡可能公平的方式安排任務,這意味著較早安排的任務將更可能較早運行,而較晚安排運行的任務將更可能較晚運行。PreferFairness = 1,//// 摘要:// 指定任務將是長時間運行的、粗粒度的操作,涉及比細化的系統更少、更大的組件。它會向 System.Threading.Tasks.TaskScheduler// 提示,過度訂閱可能是合理的。您可以通過過度訂閱創建比可用硬件線程數更多的線程。LongRunning = 2,//// 摘要:// 指定將任務附加到任務層次結構中的某個父級。有關詳細信息,請參閱 已附加和已分離的子任務。AttachedToParent = 4,//// 摘要:// 如果嘗試附有子任務到創建的任務,指定 System.InvalidOperationException 將被引發。DenyChildAttach = 8,//// 摘要:// 防止環境計劃程序被視為已創建任務的當前計劃程序。這意味著像 StartNew 或 ContinueWith 創建任務的執行操作將被視為 System.Threading.Tasks.TaskScheduler.Default// 當前計劃程序。HideScheduler = 16 } View Code2、Task.Factory.StartNew
Action,Action<object>,object state,CancellationToken,TaskCreationOptions,TaskScheduler
TaskScheduler:定義:用于計劃所創建的 System.Threading.Tasks.Task 的 System.Threading.Tasks.TaskScheduler。(并看不出來是什么意思,英文意思 任務調度器)
返回值是一個Task
Task.Factory.StartNew(() => {for (int i = 10; i < 20; i++){Console.WriteLine(i);} }); View Code3、TaskFactory
Task.Factory是TaskFactory的一個實例。
TaskFactory tf = new TaskFactory(); tf.StartNew(() => {for (int i = 20; i < 30; i++){Console.WriteLine(i);} }); View Code?上面的都是不帶返回參數的任務
Task創建有返回值一般項目中的返回類型都會特定的封裝一個通用的類型。所有都會有返回值。
Task<string> t = new Task<string>(GetName); t.Start(); Console.WriteLine(t.Result); Console.WriteLine("結束"); View Code public static string GetName() {for (int i = 0; i < 10; i++){Console.WriteLine(i);}return "臧峰"; } View Code注意在獲取返回值的時候,t.Result會卡著線程,一只等待線程返回結果。
Task等待1、為什么要等待呢,因為線程大部分都要計算已給結果,所以我們要等待這個結果。
2、public void Wait(。。。。);
位于Task類中(實例方法。另外還有幾個靜態方法)。
定義:等待 System.Threading.Tasks.Task 完成執行過程(卡著其他線程)。
參數可以設置等待時間,CancellationToken(任務取消) ?等待期間可以取消任務。
3、public static void WaitAll(params Task[] tasks....);
定義:等待提供的所有 System.Threading.Tasks.Task 對象完成執行過程。(就是當前線程要等這個參數列表中線程全部執行完后 ?才執行。注意:waitall前面其他的子線程還是在繼續執行)
參數:等待任務列表,事件,CancellationToken
4、public static int WaitAny(params Task[] tasks);
定義:等待提供的任一 System.Threading.Tasks.Task 對象完成執行過程。
參數:等待任務列表,事件,CancellationToken
5、Task的屬性方法
| AsyncState | 就是當任務核心方法帶參數的時候,參數值 |
| Status | 任務執行進度的狀態 |
| CreationOptions | 任務創建和執行的行為 |
| Id | 任務線程ID |
| IsCanceled | 任務是否被取消 |
| IsCompleted | 任務是否完成 |
| IsFaulted | 任務是否失敗 |
| Result | 任務返回值,該值只適用于有返回參數的任務 |
?
?
?
?
?
?
| ContinueWith() | 線程執行完之后執行另外一個任務 |
| GetAwaiter() | 獲取等待這個線程的等待著 |
| Start() | 發起一個任務 |
| Wait() | 當前調用wait的任務線程等待 |
?
?
?
這些是常用的
?
?
Task回調 //------------------------Task回調------------------------- Task<int> t = new Task<int>(() => {var temp = 0;for (int i = 0; i < 10; i++){temp += i;}return temp; });t.ContinueWith<string>((f) => {Console.WriteLine(f.Result.ToString());return f.Result.ToString(); }); t.Start();//------------------TaskFactory回調---------------------------- TaskFactory<int> tf = new TaskFactory<int>(); var tft = tf.StartNew(() =>{var temp = 0;for (int i = 0; i < 10; i++){temp += i;}return temp;}); tft.ContinueWith<string>((f) => {Console.WriteLine(f.Result.ToString());return f.Result.ToString(); });//-----------------------ContinueWhenAll-------------------------- var cts = new CancellationTokenSource(); TaskFactory<int> tf1 = new TaskFactory<int>(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);Task<int> t1 = tf1.StartNew(() => { Console.WriteLine(1); return 1; }); Task<int> t2 = tf1.StartNew(() => { Console.WriteLine(2); return 2; }); Task<int> t3 = tf1.StartNew(() => { Console.WriteLine(3); return 3; }); Task<int> t4 = tf1.StartNew(() => { Console.WriteLine(4); return 4; }); Task<int> t5 = tf1.StartNew(() => { Console.WriteLine(5); return 5; });//意思就是說當這些所有的線程都執行完了,在執行后面的線程 //第一個參數就是要執行的線程數組 //第二個參數就是 繼續執行的線程 var tcwa = tf1.ContinueWhenAll(new[] { t1, t2, t3, t4, t5 }, tlReturn =>{int temp = 0;for (int i = 0; i < tlReturn.Length; i++){temp += tlReturn[i].Result;}Console.WriteLine(temp);return temp;});var tft1 = tf1.StartNew(() => {var temp = 0;for (int i = 0; i < 10; i++){temp += i;}Console.WriteLine(temp);return temp; });//-------------------------FromAsync----------------------------------- TaskFactory<long> tfFA = new TaskFactory<long>(); Func<long> faDel = (() => {Console.WriteLine("臧鋒");return 10; }); tfFA.FromAsync(faDel.BeginInvoke(null, null), (tr) => {Console.WriteLine(tr.IsCompleted);return 11; }); View Code還是先了解一下TaskFactory
ContinueWhen不會卡當前線程。wait會卡當前線程。
| CancellationToken | 任務取消標記 |
| ContinuationOptions | 字面意思 任務延續選擇。官方注釋不敢恭維。和ContinueWhenAll、ContinueWhenAny有關 |
| CreationOptions | 指定此任務工廠的默認創建選項。(任務執行順序,是否長時間執行...) |
| Scheduler | 任務工廠的任務計劃程序。表示一個處理將任務排隊到線程中的低級工作的對象。 |
?
?
?
?
?
| ContinueWhenAll | 創建一個延續任務,它將在提供的組中的所有任務完成后馬上開始。第一個參數P1:線程列表,就是要執行的線程 (必須有調用ContinueWhenAll的TaskFactory創建) ? ?第二個參數P2:回調函數 (回調函數的第一個參數為第一個參數P1,回調函數第二個參數為返回值,由TaskFactory<>定義的)。 ? 執行順序 ?P1先執行,然后P2執行。 ? TaskFactory的任務為隨機執行 |
| ContinueWhenAny | 創建一個延續任務,它將在提供的組中的任何任務完成后馬上開始。 |
| FromAsync | 創建一個任務,它在指定的 System.IAsyncResult 完成時執行一個結束方法函數。(官方解釋有點繞 ?其實就是 通過它可以把一個異步的任務轉換為一個Task,返回值是一個Task,最后在執行一個回調函數) ? ? 吐槽一下,官方的翻譯是不是都是電腦翻譯的。 |
| StartNew | 創建開啟任務 |
?
Task取消主要是類CancellationTokenSource
定義:通知 System.Threading.CancellationToken,告知其應被取消。
可以馬上取消,還可以設置時間取消。
CancellationTokenSource clt = new CancellationTokenSource(); TaskFactory tf = new TaskFactory(clt.Token); tf.StartNew(() => {int temp = 0;for (int i = 0; i < 10000; i++){Thread.Sleep(10);if (!clt.IsCancellationRequested){temp += i;}else{break;}}Console.WriteLine(temp); }); Thread.Sleep(200); clt.Cancel(); View Code Task返回值具有返回值的是要用泛型 ?指定返回值類型。
Task<int> t = new Task<int>(() => 5); t.Start(); Console.WriteLine(t.Result);TaskFactory<int> tf = new TaskFactory<int>(); var tft= tf.StartNew(() => { return 6; }); Console.WriteLine(tft.Result); View Code最后通過Task.Result得到結果。這個操作會卡著線程,一直等待回去結果。
?Parallel并行任務1、Parallel ?定義:提供對并行循環和區域的支持。靜態類,靜態方法。他是基于Task,線程池。
其實是操作循環任務,但是循環的任務都是在平行執行的,沒人先后順序,但是,循環結會等待他們都結束的。
Parallel.For
Parallel.ForEach
Parallel.Invok
優點:主線程也會參與計算,缺點:就是會waitall ? 會卡住當前線程。
?
2、ParallelLoopResult 定義:提供執行 System.Threading.Tasks.Parallel 循環的完成狀態。其實就是For和ForEach的返回值
3、ParallelLoopState 定義:可用來使 System.Threading.Tasks.Parallel 循環的迭代與其他迭代交互。此類的實例由 Parallel 類提供給每個循環;不能在您的用戶代碼中創建實例。
他可以讓循環退出 ,通知。 ?(就像for循環中的bread)
4、ParallelOptions 定義:存儲用于配置 System.Threading.Tasks.Parallel 類的方法的操作的選項。
// // 摘要: // 獲取或設置與此 System.Threading.Tasks.ParallelOptions 實例關聯的 System.Threading.CancellationToken。 // // 返回結果: // 與此實例關聯的標記。 public CancellationToken CancellationToken { get; set; } // // 摘要: // 獲取或設置此 System.Threading.Tasks.ParallelOptions 實例所允許的最大并行度。 // // 返回結果: // 一個表示最大并行度的整數。 // // 異常: // T:System.ArgumentOutOfRangeException: // 該屬性被設置為 0 或小于 -1 的值。 public int MaxDegreeOfParallelism { get; set; } // // 摘要: // 獲取或設置與此 System.Threading.Tasks.ParallelOptions 實例關聯的 System.Threading.Tasks.TaskScheduler。將此屬性設置為 // null,以指示應使用當前計劃程序。 // // 返回結果: // 與此實例關聯的任務計劃程序。 public TaskScheduler TaskScheduler { get; set; } View Code可以取消任務,并行的數量(循環中一次并行執行任務的個數,當任務量比較大的時候,一定要指定這個值,不然電腦可能撐不住。但是他是基于線程池的,線程池會幫我們控制一下,但是還是會卡電腦。并行數量控制,導致起的線程是一輪一輪的,每一輪第一個線程ID都一樣,用的主線程ID)
5、總結
?Parallel.For()和Paraller.ForEach()方法在每次迭代中調用相同的代碼,而Parallel.Invoke()方法允許同時調用不同的方法。Parallel.ForEach()用于數據并行性,Parallel.Invoke()用于任務并行性;
主線程可以參與計算,但是要waitall。等待。
Await Async1、出現介紹
C#5.0 ? ? ? ? ? ? ? ? ?C#語言版本
.net fromwork 4.5 ? ? ? ? ? ? ? ?框架類庫版本FCL
clr4.0 ? ? ? ? ? ? ? ? ?CLR版本
await async他是一個語法糖。什么是語法糖呢,就是c#或者.net fromwork改變但是clr沒有改變。
泛型就不是語法糖,他出現的時候clr重寫了,就是使用泛型的地方, ?對應的生成相應的類型方法。
沒有task就沒有await async
2、原理
是一個語法糖,利用一個狀態機的概念,通過編譯器編譯把await后面的代碼封裝為一個委托進行回調執行,并且await會等待執行完成,狀態機就是這一個執行完之后,就movenest執行下一個回調。就是await一層層的嵌套就可以了。
3、使用
await只能出現在task前面,await后面的代碼變成task的回調。快速的寫出了異步回調
返回值只能是void task ?task<>,推薦使用task<>返回值,并封裝通用T類型。
?
本文代碼下載
補充例子
轉載于:https://www.cnblogs.com/wudequn/p/7571039.html
總結
以上是生活随笔為你收集整理的多线程-Task、await/async的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GC及其作用
- 下一篇: IE下iframe跨域session和c