C#實(shí)現(xiàn)異步的常用方式總結(jié)
前言
微信群里的一個(gè)提問引發(fā)的這個(gè)問題,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)方式
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);
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 async void Main(string[] args)
{
await Task.Run(() =>
{
Console.WriteLine("Test Task 1 completed.");
});
await Task.Run(() =>
{
Console.WriteLine("Test Task 2 completed.");
});
// 等待所有任務(wù)完成
Task.WaitAll();
}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 模式更加簡(jiǎn)潔易懂,同時(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);
}
}以上就是C#實(shí)現(xiàn)異步的常用方式總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于C#異步的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity學(xué)習(xí)之FSM有限狀態(tài)機(jī)
這篇文章主要介紹了Unity學(xué)習(xí)之FSM有限狀態(tài)機(jī),通過詳細(xì)的代碼案例來進(jìn)行解析說明,希望這篇文章對(duì)你有所幫助2021-06-06
C# Oracle批量插入數(shù)據(jù)進(jìn)度條的實(shí)現(xiàn)代碼
這篇文章主要介紹了C# Oracle批量插入數(shù)據(jù)進(jìn)度條的實(shí)現(xiàn)代碼,需要的朋友可以參考下2018-04-04
基于C#實(shí)現(xiàn)獲取Windows所有窗口句柄
在做錄屏或截屏操作時(shí),需要獲取當(dāng)前正在運(yùn)行中的桌面程序句柄,所以這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)獲取Windows所有窗口句柄,需要的可以參考下2023-12-12
C#實(shí)現(xiàn)Stripe支付的方法實(shí)踐
本文主要介紹了C#實(shí)現(xiàn)Stripe支付的方法實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
在C#中如何使用ResNet50v2進(jìn)行圖像識(shí)別
ONNX?運(yùn)行時(shí)推理可以實(shí)現(xiàn)更快的客戶體驗(yàn)和更低的成本,支持來自深度學(xué)習(xí)框架如?PyTorch和TensorFlow/Keras以及經(jīng)典機(jī)器學(xué)習(xí)庫如?scikit-learn、LightGBM、XGBoost?等的模型,這篇文章主要介紹了在C#中如何使用ResNet50v2進(jìn)行圖像識(shí)別,需要的朋友可以參考下2024-07-07
C#使用ICSharpCode.SharpZipLib.dll進(jìn)行文件的壓縮與解壓功能
這篇文章主要介紹了C#使用ICSharpCode.SharpZipLib.dll進(jìn)行文件的壓縮與解壓功能,需要的朋友可以參考下2017-12-12

