C#中異步是4種實(shí)現(xiàn)方式詳解
前言
微信群里的一個(gè)提問引發(fā)的這個(gè)問題,有同學(xué)問:C#異步有多少種實(shí)現(xiàn)方式?想要知道C#異步有多少種實(shí)現(xiàn)方式,首先我們要知道.NET提供的執(zhí)行異步操作的三種模式,然后再去了解C#異步實(shí)現(xiàn)的方式。
.NET異步編程模式
.NET 提供了執(zhí)行異步操作的三種模式:
基于任務(wù)的異步模式 (TAP) ,該模式使用單一方法表示異步操作的開始和完成。TAP 是在 .NET Framework 4 中引入的。 這是在 .NET 中進(jìn)行異步編程的推薦方法。C# 中的 async 和 await 關(guān)鍵詞以及 Visual Basic 中的 Async 和 Await 運(yùn)算符為 TAP 添加了語言支持。有關(guān)詳細(xì)信息,請(qǐng)參閱基于任務(wù)的異步模式 (TAP)。
基于事件的異步模式 (EAP),是提供異步行為的基于事件的舊模型。這種模式需要后綴為 Async 的方法,以及一個(gè)或多個(gè)事件、事件處理程序委托類型和 EventArg 派生類型。EAP 是在 .NET Framework 2.0 中引入的。建議新開發(fā)中不再使用這種模式。有關(guān)詳細(xì)信息,請(qǐng)參閱基于事件的異步模式 (EAP)。
異步編程模型 (APM) 模式(也稱為 IAsyncResult 模式),這是使用 IAsyncResult 接口提供異步行為的舊模型。在這種模式下,同步操作需要 Begin 和 End 方法(例如,BeginWrite 和 EndWrite以實(shí)現(xiàn)異步寫入操作)。不建議新的開發(fā)使用此模式。有關(guān)詳細(xì)信息,請(qǐng)參閱異步編程模型 (APM)。
C#異步四種實(shí)現(xiàn)方式
1、異步方法(Async Method TAP模式)
使用async/await關(guān)鍵字實(shí)現(xiàn)異步編程,這是比較常用的一種異步實(shí)現(xiàn)方式。例如:
public async Task TestDoSomeAsync() { await Task.Delay(1000*10); Console.WriteLine("Async method completed."); }
2、任務(wù)并行庫(TPL, Task Parallel Library TAP模式)
通過 Task 和 Task<T> 類型實(shí)現(xiàn)異步編程,可以利用多核處理器,并發(fā)執(zhí)行多個(gè)獨(dú)立的任務(wù)。例如:
public static void TestTaskParallel() { var task1 = Task.Run(() => { Console.WriteLine("Task 1 completed."); }); var task2 = Task.Run(() => { Console.WriteLine("Task 2 completed."); }); Task<int> task3 = Task.Factory.StartNew(() => { Console.WriteLine("Task 3 completed."); return 20;// 返回一個(gè)整數(shù)值 }); //等待所有任務(wù)完成 Task.WaitAll(task1, task2, task3); }
3、Asynchronous Programming Model(APM模式)
是一種經(jīng)典的異步編程模式,需要手動(dòng)創(chuàng)建回調(diào)函數(shù),用于處理完成或錯(cuò)誤的通知??梢酝ㄟ^ IAsyncResult 設(shè)計(jì)模式的 Begin 和 End 方法來實(shí)現(xiàn),其中 Begin 方法開始異步操作,而 End 方法在異步操作完成時(shí)執(zhí)行,并返回異步操作的結(jié)果。
需要注意的是,APM 模式通過 IAsyncResult 接口來存儲(chǔ)異步操作的狀態(tài)和結(jié)果,相對(duì)比較復(fù)雜,代碼量也較大。同時(shí),在使用 APM 模式時(shí),還需要手動(dòng)處理回調(diào)函數(shù)和等待異步操作完成等細(xì)節(jié)工作,使得開發(fā)起來相對(duì)較為繁瑣。
class Program { static void Main(string[] args) { // 創(chuàng)建異步操作類實(shí)例 MyAsyncClass asyncClass = new MyAsyncClass(); // 開始異步操作 IAsyncResult result = asyncClass.BeginDoWork(null, null); // 主線程執(zhí)行其他操作 // 等待異步操作完成并獲取結(jié)果 int res = asyncClass.EndDoWork(result); // 處理異步操作的結(jié)果 Console.WriteLine("Result: " + res); Console.ReadLine(); } } class MyAsyncClass { /// <summary> /// 異步執(zhí)行的方法 /// </summary> /// <param name="callback">callback</param> /// <param name="state">state</param> /// <returns></returns> public IAsyncResult BeginDoWork(AsyncCallback callback, object state) { // 創(chuàng)建一個(gè)新的異步操作對(duì)象 MyAsyncResult result = new MyAsyncResult(state); // 開始異步操作 Thread thread = new Thread(() => { try { // 執(zhí)行一些操作 int res = 1 + 2; // 設(shè)置異步操作的結(jié)果 result.Result = res; // 觸發(fā)回調(diào)函數(shù) callback?.Invoke(result); } catch (Exception ex) { // 設(shè)置異步操作的異常 result.Error = ex; // 觸發(fā)回調(diào)函數(shù) callback?.Invoke(result); } }); thread.Start(); // 返回異步操作對(duì)象 return result; } /// <summary> /// 結(jié)束異步執(zhí)行的方法 /// </summary> /// <param name="result">result</param> /// <returns></returns> public int EndDoWork(IAsyncResult result) { // 將 IAsyncResult 轉(zhuǎn)換為 MyAsyncResult 類型,并等待異步操作完成 MyAsyncResult myResult = (MyAsyncResult)result; myResult.AsyncWaitHandle.WaitOne(); // 在異步操作中拋出異常 if (myResult.Error != null) { throw myResult.Error; } // 返回異步操作的結(jié)果 return myResult.Result; } } class MyAsyncResult : IAsyncResult { public bool IsCompleted => AsyncWaitHandle.WaitOne(0); public WaitHandle AsyncWaitHandle { get; } = new ManualResetEvent(false); public object AsyncState { get; } public bool CompletedSynchronously => false; public int Result { get; set; } /// <summary> /// 存儲(chǔ)異步操作的結(jié)果或異常信息 /// </summary> public Exception Error { get; set; } /// <summary> /// 構(gòu)造函數(shù) /// </summary> /// <param name="asyncState">asyncState</param> public MyAsyncResult(object asyncState) { AsyncState = asyncState; } }
4、Event-based Asynchronous Pattern(EAP模式)
一種已過時(shí)的異步編程模式,需要使用事件來實(shí)現(xiàn)異步編程。例如:
需要注意的是,EAP 模式通過事件來實(shí)現(xiàn)異步編程,相對(duì)于 APM 模式更加簡潔易懂,同時(shí)也避免了手動(dòng)處理回調(diào)函數(shù)等細(xì)節(jié)工作。但是,EAP 模式并不支持 async/await 異步關(guān)鍵字,因此在一些特定的場(chǎng)景下可能不夠靈活。
public class MyAsyncClass : Component { /// <summary> /// 聲明一個(gè)委托類型,用于定義異步操作的方法簽名 /// </summary> /// <param name="arg"></param> /// <returns></returns> public delegate int MyAsyncDelegate(int arg); /// <summary> /// 聲明一個(gè)事件,用于通知異步操作的完成 /// </summary> public event MyAsyncDelegate OperationNameCompleted; /// <summary> /// 異步執(zhí)行方法,接受一個(gè)參數(shù) arg /// </summary> /// <param name="arg"></param> public void DoWorkAsync(int arg) { // 將異步操作放入線程池中執(zhí)行 ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), arg); } /// <summary> /// 真正的異步操作 /// </summary> /// <param name="obj"></param> private void DoWork(object obj) { int arg = (int)obj; int res = arg + 1; // 觸發(fā)事件,傳遞異步操作的結(jié)果 OperationNameCompleted?.Invoke(res); } }
使用總結(jié)
綜合上面三種執(zhí)行異步操作的模式而言,得出以下結(jié)論:TAP適合簡單的并行場(chǎng)景,EAP更適合清晰的控制有來有往的多端異步場(chǎng)景,APM更適合控制求解復(fù)雜結(jié)構(gòu)的返回值的場(chǎng)景。各有各種方便的地方,也各有表達(dá)困難的地方,有的方法看著麻煩,但是思路清晰,便于調(diào)試。有的辦法看似簡單,結(jié)合交互通信就讓人費(fèi)解。不是說新的就一定好,合適的方法才是最好的。
到此這篇關(guān)于C#中異步是4種實(shí)現(xiàn)方式詳解的文章就介紹到這了,更多相關(guān)C#異步內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#和avascript加解密之間的互轉(zhuǎn)代碼分享
這篇文章主要介紹了c#和Javascript間互轉(zhuǎn)的Xxtea加解密代碼,需要的朋友可以參考下2014-02-02C#實(shí)現(xiàn)將程序鎖定到Win7任務(wù)欄的方法
這篇文章主要介紹了C#實(shí)現(xiàn)將程序鎖定到Win7任務(wù)欄的方法,涉及C#調(diào)用Shell類的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08C# 打印網(wǎng)頁不顯示頁眉頁腳的實(shí)現(xiàn)方法
這篇文章主要介紹了C# 打印網(wǎng)頁不顯示頁眉頁腳的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01C#數(shù)據(jù)庫操作類AccessHelper實(shí)例
這篇文章主要介紹了C#數(shù)據(jù)庫操作類AccessHelper實(shí)例,可實(shí)現(xiàn)針對(duì)access數(shù)據(jù)庫的各種常見操作,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10基于C#實(shí)現(xiàn)文字轉(zhuǎn)語音功能
這篇文章將在C#中集成一個(gè)語音對(duì)象SpeechSynthesizer,可以根據(jù)填入的文字內(nèi)容自動(dòng)解析成語音并使用系統(tǒng)揚(yáng)聲器進(jìn)行語音播報(bào),感興趣的小伙伴可以了解下2025-02-02c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07