日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

C#异步编程模型

發(fā)布時(shí)間:2023/12/10 C# 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#异步编程模型 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是異步編程模型

異步編程模型(Asynchronous Programming Model,簡(jiǎn)稱APM)是C#1.1支持的一種實(shí)現(xiàn)異步操作的編程模型,雖然已經(jīng)比較“古老”了,但是依然可以學(xué)習(xí)一下的。通過(guò)對(duì)APM的學(xué)習(xí),我總結(jié)了以下三點(diǎn):

1. APM的本質(zhì)是使用委托和線程池來(lái)實(shí)現(xiàn)異步編程的。

2.?實(shí)現(xiàn)APM的關(guān)鍵是要實(shí)現(xiàn)IAsyncResult接口

3. 實(shí)現(xiàn)了APM的類都會(huì)定義一對(duì)形如BeginXXX()和EndXXX()的方法,例如,FileStream類定義了BeginRead()方法和EndRead()方法,可以實(shí)現(xiàn)異步讀取文件內(nèi)容。

下面我們就通過(guò)具體的代碼來(lái)實(shí)現(xiàn)異步編程模型。

實(shí)現(xiàn)異步編程模型

1. 實(shí)現(xiàn)IAsyncResult接口

IAsyncResult接口是C#類庫(kù)中定義的一個(gè)接口,表示異步操作的狀態(tài),具體介紹可以查看MSDN。

?

1 public interface IAsyncResult2 {3 object AsyncState { get; }4 5 WaitHandle AsyncWaitHandle { get; }6 7 bool CompletedSynchronously { get; }8 9 bool IsCompleted { get; } 10 }

上面的代碼是IAsyncResult接口聲明的四個(gè)屬性:

1. AsyncState屬性是一個(gè)用戶定義的對(duì)象,包含異步操作狀態(tài)信息。例如,當(dāng)我們調(diào)用FileStream類的BeginRead()方法進(jìn)行異步讀取文件內(nèi)容時(shí),傳入的最后一個(gè)參數(shù)對(duì)應(yīng)的就是AsyncState屬性。

2. AsyncWaitHandle屬性主要的作用是阻塞當(dāng)前線程來(lái)等待異步操作完成。WaitHandle抽象類,有一個(gè)很重要的派生類ManualResetEvent。

3. CompletedSynchronously屬性比較特別,用來(lái)判斷異步操作是否是同步完成(這個(gè)有點(diǎn)兒繞~)。

4. IsCompleted屬性就比較簡(jiǎn)單了,用來(lái)判斷異步操作是否完成,true表示已完成,false表示還未完成。

在實(shí)現(xiàn)IAsyncResult接口時(shí),我們主要會(huì)用到AsyncState,IsCompleted和AsyncWaitHandle屬性。

1 /// <summary>2 /// CalculatorAsyncResult<T>類,實(shí)現(xiàn)了IAsyncResult接口3 /// </summary>4 /// <typeparam name="T"></typeparam>5 public class CalculatorAsyncResult<T> : IAsyncResult6 {7 private ManualResetEvent _waitHandle;8 9 private object _asyncState;10 11 private bool _completedSynchronously;12 13 private bool _isCompleted;14 15 //我們傳入的異步回調(diào)方法16 private AsyncCallback _asyncCallback;17 18 //保存異步操作返回結(jié)果19 public T CalulatorResult { get; set; }20 21 public static CalculatorAsyncResult<T> CreateCalculatorAsyncResult(Func<T> work, AsyncCallback asyncCallback, object obj)22 {23 var asyncResult = new CalculatorAsyncResult<T>(obj, asyncCallback, false, false);24 25 asyncResult.ExecuteWork(work);26 27 return asyncResult;28 }29 30 public CalculatorAsyncResult(object obj, AsyncCallback asyncCallback, bool completedSynchronously, bool isCompleted)31 {32 _waitHandle = new ManualResetEvent(false);33 34 _asyncState = obj;35 36 _completedSynchronously = completedSynchronously;37 38 _isCompleted = isCompleted;39 40 _asyncCallback = asyncCallback;41 }42 43 public object AsyncState44 { 45 get { return _asyncState; } 46 }47 48 public WaitHandle AsyncWaitHandle49 {50 get{ return _waitHandle; }51 }52 53 public bool CompletedSynchronously54 {55 get { return _completedSynchronously; }56 }57 58 public bool IsCompleted59 {60 get { return _isCompleted; }61 }62 63 public void Wait()64 {65 _waitHandle.WaitOne();66 }67 68 /// <summary>69 /// 調(diào)用異步回調(diào)方法70 /// </summary>71 private void InvokeAsyncCallback()72 {73 _isCompleted = true;74 75 if (_waitHandle != null)76 {77 _waitHandle.Set();78 }79 80 //調(diào)用我們傳入的異步回調(diào)方法81 _asyncCallback(this);82 }83 84 /// <summary>85 /// 執(zhí)行異步工作86 /// </summary>87 /// <param name="work"></param>88 public void ExecuteWork(Func<T> work)89 {90 if(_asyncCallback != null)91 {92 Task<T> task = Task.Factory.StartNew<T>(work);93 94 task.ContinueWith(t => 95 {96 CalulatorResult = t.Result;97 98 InvokeAsyncCallback();99 }); 100 } 101 else 102 { 103 _isCompleted = true; 104 105 if(_waitHandle != null) 106 { 107 _waitHandle.Set(); 108 } 109 } 110 } 111 }

2. 定義BeginXXX()和EndXXX()方法

下面就來(lái)定義我們自己的APM接口和具體實(shí)現(xiàn)類,編寫(xiě)B(tài)eginXXX()和EndXXX()方法。

1 /// <summary>2 /// 異步計(jì)算接口3 /// </summary>4 /// <typeparam name="T"></typeparam>5 public interface ICalculator<T>6 {7 IAsyncResult BeginAdd(T x, T y, AsyncCallback asyncCallback, Object obj);8 9 T EndAdd(IAsyncResult ar); 10 }

1 /// <summary>2 /// 異步計(jì)算接口實(shí)現(xiàn)類3 /// </summary>4 public class Calculator : ICalculator<double>5 {6 public IAsyncResult BeginAdd(double x, double y, AsyncCallback asyncCallback, Object obj)7 {8 return CalculatorAsyncResult<double>.CreateCalculatorAsyncResult(delegate { return Add(x, y); }, asyncCallback, obj);9 } 10 11 public double EndAdd(IAsyncResult ar) 12 { 13 var calculatorAsyncResult = (CalculatorAsyncResult<double>)(ar); 14 15 calculatorAsyncResult.Wait(); 16 17 return calculatorAsyncResult.CalulatorResult; 18 } 19 20 /// <summary> 21 /// 計(jì)算方法 22 /// </summary> 23 /// <param name="x"></param> 24 /// <param name="y"></param> 25 /// <returns></returns> 26 protected double Add(double x, double y) 27 { 28 Console.WriteLine("Async thread(id={0}) begins.\n", Thread.CurrentThread.ManagedThreadId); 29 30 Console.WriteLine("Async thread(id={0}) is calculating...\n", Thread.CurrentThread.ManagedThreadId); 31 32 Thread.Sleep(3000); 33 34 var r = x + y; 35 36 Console.WriteLine("Async thread(id={0}) ends.\n", Thread.CurrentThread.ManagedThreadId); 37 38 return r; 39 } 40 }

3. 獲取異步操作結(jié)果

APM提供了四種獲取異步操作的結(jié)果方式供我們選擇:

1.?通過(guò)IAsyncResult的AsyncWaitHandle屬性,調(diào)用它的WaitOne()方法使調(diào)用線程阻塞來(lái)等待異步操作完成再調(diào)用EndXXX()方法來(lái)獲取異步操作結(jié)果。

2. 在調(diào)用BeginXXX()方法的線程上調(diào)用EndXXX()方法來(lái)獲取異步操作結(jié)果。這種方式也會(huì)阻塞調(diào)用線程(阻塞原理同方式1,具體在上面的代碼中有體現(xiàn))。

3. 輪詢IAsyncResult的IsComplete屬性,當(dāng)異步操作完成后再調(diào)用EndXXX()方法來(lái)獲取異步操作結(jié)果。

4.?使用 AsyncCallback委托來(lái)指定異步操作完成時(shí)要回調(diào)的方法,在回調(diào)方法中調(diào)用EndXXX()方法來(lái)獲取異步操作結(jié)果。

在上述的四種方式中,只有第四種方式是完全不會(huì)阻塞調(diào)用線程的,所以多數(shù)情況下我們都會(huì)選擇回調(diào)的方式來(lái)獲取異步操作結(jié)果。

1 public class Program2 {3 public static double result = 0;4 5 static void Main(string[] args)6 {7 Console.WriteLine("Main thread(id={0}) begins.\n", Thread.CurrentThread.ManagedThreadId);8 9 var calculator = new Calculator(); 10 11 Console.WriteLine("Main thread(id={0}) invokes BeginAdd() function.\n", Thread.CurrentThread.ManagedThreadId); 12 13 calculator.BeginAdd(1, 2, Callback, calculator); 14 15 Console.WriteLine("Main thread(id={0}) is sleeping...\n", Thread.CurrentThread.ManagedThreadId); 16 17 Thread.Sleep(5000); 18 19 Console.WriteLine("The calculating result of async operation is {0}.\n", result); 20 21 Console.WriteLine("Main thread(id={0}) ends.\n", Thread.CurrentThread.ManagedThreadId); 22 } 23 24 /// <summary> 25 /// 我們定義的回調(diào)方法 26 /// </summary> 27 /// <param name="ar"></param> 28 public static void Callback(IAsyncResult ar) 29 { 30 var calculator = (Calculator)(ar.AsyncState); 31 32 result = calculator.EndAdd(ar); 33 } 34 }

運(yùn)行結(jié)果:

至此,我們已經(jīng)完整地實(shí)現(xiàn)了APM異步編程模型,從運(yùn)行結(jié)果中我們可以得出,通過(guò)回調(diào)的方式來(lái)獲取異步操作結(jié)果是完全不會(huì)阻塞調(diào)用線程的。

總結(jié)

1. 實(shí)現(xiàn)APM的關(guān)鍵是實(shí)現(xiàn)IAsyncResult接口。在IAsyncResult實(shí)現(xiàn)類中,需要使用線程池來(lái)異步地執(zhí)行操作,在操作完成之后,再調(diào)用傳入的回調(diào)方法來(lái)返回操作結(jié)果。

2. 實(shí)現(xiàn)了APM的類中都會(huì)定義一對(duì)BeginXXX()和EndXXX()方法,開(kāi)始異步操作,結(jié)束異步操作并返回異步操作結(jié)果。

3. 獲取異步操作結(jié)果有四種方式,但是只有回調(diào)方式是完全不會(huì)阻塞調(diào)用線程的,其他的都會(huì)阻塞調(diào)用線程。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的C#异步编程模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。