C#異步使用需要注意的幾個問題
一、異步模型的基本概述
異步編程的核心是 Task
和 Task<T>
對象,這兩個對象對異步操作建模。 它們受關(guān)鍵字 async
和 await
的支持。 在大多數(shù)情況下模型十分簡單:
對于 I/O 綁定代碼,當(dāng)你 await
一個操作,它將返回 async
方法中的一個 Task
或 Task<T>
。
對于 CPU 綁定代碼,當(dāng)你 await
一個操作,它將在后臺線程通過 Task.Run()
方法啟動。
二、C#異步使用需要注意的幾個問題
- 異步方法如果只是對別的方法的簡單的轉(zhuǎn)發(fā)調(diào)用,沒喲復(fù)雜的邏輯(比如等待A的結(jié)果,再調(diào)用B,等待A調(diào)用的返回值拿到內(nèi)部做一些處理再返回),那么就可以去掉async關(guān)鍵字。
- 異步方法其實使用async 關(guān)鍵字clr多了一些準(zhǔn)備和 轉(zhuǎn)換的處理和線程的切換,效率反而低。
- 異步方法中想暫停一段時間,不要用thread.sleep(),因為他會阻塞調(diào)用線程導(dǎo)致當(dāng)前界面卡無響應(yīng),而要用await task.delay(); 例如6秒后下載一個文件
- 異步中的CancellationToken 參數(shù),用于提前終止任務(wù),比如取消任務(wù),請求超時
三、CancellationToken 結(jié)構(gòu)體
- None 空
- bool IsCancellationToken 是否取消
- Register(action callback)注冊取消監(jiān)聽
- ThrowIfCancellationRequested 如果任務(wù)被取消,執(zhí)行到這句話就拋異常
- CancellationTokenSource 來創(chuàng)建 CancellationToken
- CancelAfter()超時后發(fā)出取消信號
- Cancel()發(fā)出取消信號
- CancellationToken Token
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(5000); //超時5s后取消 await DownloadString("http://www.baidu.com", 50, cts.Token); }
1.手動取消
if (cancellationToken.IsCancellationRequested) { Console.WriteLine("任務(wù)被取消"); break; }
2.利用方法取消,拋出異常
cancellationToken.ThrowIfCancellationRequested();
3. 傳參數(shù)取消
系統(tǒng)自帶的異步方法,只需要傳參數(shù)就可取消,拋出異常
var resp= await client.GetAsync(url,cancellationToken);
4.手動觸發(fā)事件取消任務(wù)
static async Task Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); //cts.CancelAfter(5000); DownloadString("http://www.baidu.com", 100, cts.Token); //和超時區(qū)別在于去掉了前面的await 才生效 while (Console.ReadLine() != "q") { } cts.Cancel(); Console.ReadLine(); }
.Asp.net core Mvc
控制器里面的異步方法盡量帶 CancellationToken
5.Task類方法
WhenAny
任何一個Task
完成,task
就完成WhenAll
所有任務(wù)都完成,才完成 。 不在乎Task
執(zhí)行順序FromResult
創(chuàng)建普通數(shù)值的Task
對象
6.yield流水線返回
yield 可以流水線返回,提高性能。
C# 8.0以上支持 yield異步方法的使用
static async IAsyncenumerable<string> test() { yield return "a"; yield return "b"; yield return "c"; }
調(diào)用:
await foreach(var o in test()) { Console.WriteLine(o); }
public static async Task DownloadString(string url,int num,CancellationToken cancellationToken) { try { using (var client = new HttpClient()) { for (int i = 0; i < num; i++) { string html = await client.GetStringAsync(url); Console.WriteLine($"{DateTime.Now}:{html}"); //1.手動取消 if (cancellationToken.IsCancellationRequested) { Console.WriteLine("任務(wù)被取消"); break; } //2.拋出異常 //cancellationToken.ThrowIfCancellationRequested(); } } } catch (Exception) { throw; } } public static async Task Download2String(string url, int num, CancellationToken cancellationToken) { using (var client = new HttpClient()) { for (int i = 0; i < num; i++) { var resp= await client.GetAsync(url,cancellationToken); string html =await resp.Content.ReadAsStringAsync(); Console.WriteLine($"{DateTime.Now}:{html}"); //1.手動取消 //if (cancellationToken.IsCancellationRequested) //{ // Console.WriteLine("任務(wù)被取消"); // break; //} //2.拋出異常 //cancellationToken.ThrowIfCancellationRequested(); } } }
到此這篇關(guān)于C#使用異步需要注意的幾個問題的文章就介紹到這了,更多相關(guān)C#使用異步需要注意的問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c# 通過wbemtest和WMI Code Cretor更加高效的訪問WMI
能找到這篇博客的,相信都是有操作WMI需求的了。本文將講述如何快速驗證、并集成到C#來操作WMI。2021-05-05詳細(xì)聊聊C#的并發(fā)機(jī)制優(yōu)秀在哪
并發(fā)其實是一個很泛的概念,字面意思就是"同時做多件事",不過方式有所不同,下面這篇文章主要給大家介紹了關(guān)于C#并發(fā)機(jī)制的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02C#連接Oracle數(shù)據(jù)庫字符串(引入DLL)的方式
這篇文章主要給大家介紹了關(guān)于C#連接Oracle數(shù)據(jù)庫字符串(引入DLL)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08