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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

与其他.Net异步模式和类型进行互操作

發(fā)布時間:2023/11/29 asp.net 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 与其他.Net异步模式和类型进行互操作 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

返回該系列目錄《基于Task的異步模式--全面介紹》


Tasks和異步編程模型APM(Tasks and the Asynchronous Programming Model)

從APM到Tasks

APM模式依賴兩個對應(yīng)的方法來表示一個異步操作:BeginMethodName和EndMethodName。在高級別,begin方法接受的參數(shù)和相應(yīng)的同步方法MethodName的參數(shù)是一樣的,而且還接受一個AsyncCallback和一個object state。begin方法然后返回IAsyncResult,IAsyncResult從它的AsyncState屬性返回傳遞給begin方法的object state。異步操作完成時,IAsyncResult的IsCompleted屬性會開始返回true,且會設(shè)置它的AsyncWaitHandle屬性。而且,如果begin方法的AsyncCallback參數(shù)是非空的,那么會調(diào)用callback,且將它傳給從begin方法返回的相同的IAsyncResult。當(dāng)異步操作確實(shí)完成時,會使用EndMethodName方法連接該操作,檢索任何結(jié)果或者強(qiáng)制產(chǎn)生的異常傳播。

由于APM模式結(jié)構(gòu)的本質(zhì),構(gòu)建一個APM的包裝器來將它暴露為一個TAP實(shí)現(xiàn)是相當(dāng)容易的。實(shí)際上,.Net Framework 4 以TaskFactory.FromAsync的形式提供了轉(zhuǎn)化的幫助路線。

思考.Net 中的Stream類和BeginRead/EndRead 方法,它們都代表了同步的Read方法的APM對應(yīng)版本:

public int Read(byte [] buffer, int offset, int count); … public IAsyncResult BeginRead(byte [] buffer, int offset, int count, AsyncCallback callback, object state); public int EndRead(IAsyncResult asyncResult);

利用FromAsycn,可實(shí)現(xiàn)該方法的TAP包裝器:

public static Task<int> ReadAsync(this Stream stream, byte [] buffer, int offset, int count) {if (stream == null) throw new ArgumentNullException(“stream”);return Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead,buffer, offset, count, null); }

這個使用了FromAsync的實(shí)現(xiàn)和下面的具有同樣效果:

public static Task<int> ReadAsync(this Stream stream, byte [] buffer, int offset, int count) {if (stream == null) throw new ArgumentNullException(“stream”);var tcs = new TaskCompletionSource<int>();stream.BeginRead(buffer, offset, count, iar =>{try { tcs.TrySetResult(stream.EndRead(iar)); }catch(OperationCanceledException) { tcs.TrySetCanceled(); }catch(Exception exc) { tcs.TrySetException(exc); }}, null);return tcs.Task; }

從Tasks到APM

對于現(xiàn)有的基礎(chǔ)設(shè)施期望代碼實(shí)現(xiàn)APM模式的場合,能夠采取TAP實(shí)現(xiàn)以及在期待TAP實(shí)現(xiàn)的地方使用它也是很重要的。幸好有了tasks的組合性,以及Task本身實(shí)現(xiàn)IAsyncResult的事實(shí),使用一個簡單的幫助函數(shù)就可以實(shí)現(xiàn)了(這里展示的是一個Task<TResult>的擴(kuò)展,但幾乎相同的函數(shù)可能用于非泛型的Task):

?

public static IAsyncResult AsApm<T>(this Task<T> task, AsyncCallback callback, object state) {if (task == null) throw new ArgumentNullException(“task”);var tcs = new TaskCompletionSource<T>(state);task.ContinueWith(t =>{if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions)else if (t.IsCanceled) tcs.TrySetCanceled();else tcs.TrySetResult(t.Result);if (callback != null) callback(tcs.Task);}, TaskScheduler.Default);return tcs.Task; }

現(xiàn)在,想一個有TAP實(shí)現(xiàn)的場合:

public static Task<string> DownloadStringAsync(Uri url);

且我們需要提供APM實(shí)現(xiàn):

public IAsyncResult BeginDownloadString(Uri url, AsyncCallback callback, object state); public string EndDownloadString(IAsyncResult asyncResult);

可以通過下面代碼實(shí)現(xiàn):

public IAsyncResult BeginDownloadString(Uri url, AsyncCallback callback, object state) {return DownloadStringAsync(url).AsApm(callback, state); }public string EndDownloadString(IAsyncResult asyncResult) {return ((Task<string>)asyncResult).Result; }

?

Tasks和基于事件的異步模式EAP(Event-based Asynchronous Pattern)

基于事件的異步模式依賴于一個返回void的實(shí)例MethodNameAsync方法,接收和同步方法MethodName方法相同的參數(shù),并且要實(shí)例化異步操作。實(shí)例異步操作之前,事件句柄使用相同實(shí)例上的事件注冊,然后觸發(fā)這些事件來提供進(jìn)度和完成通知。事件句柄一般都是自定義的委托類型,該委托類型利用了派生自ProgressChangedEventArgs或AsyncCompletedEventArgs的事件參數(shù)類型。

包裝一個EAP實(shí)現(xiàn)更復(fù)雜一些,因為該模式本身牽扯了比APM模式更多的變量和更少的結(jié)構(gòu)。為了演示,接下來包裝一個DownloadStringAsync方法。DownloadStringAsync接受一個Uri參數(shù),為了上報多個進(jìn)度上的統(tǒng)計數(shù)據(jù),下載時會觸發(fā)DownloadProgressChanged 事件,完成時會觸發(fā)DownloadStringCompleted 事件。最終結(jié)果是一個包含在指定Uri的頁面內(nèi)容的字符串。

public static Task<string> DownloadStringAsync(Uri url) {var tcs = new TaskCompletionSource<string>();var wc = new WebClient();wc.DownloadStringCompleted += (s,e) =>{if (e.Error != null) tcs.TrySetException(e.Error);else if (e.Cancelled) tcs.TrySetCanceled();else tcs.TrySetResult(e.Result);};wc.DownloadStringAsync(url);return tcs.Task; }

Tasks和等待句柄(WaitHandlers)

從WaitHandlers到Tasks

高級的開發(fā)人員可能會發(fā)現(xiàn),WaitHandle 設(shè)置時,自己利用 WaitHandles 和線程池的 RegisterWaitForSingleObject 方法進(jìn)行異步通知,然而這本質(zhì)上不是一個異步模式 。我們可以包裝RegisterWaitForSingleObject來啟用WaitHandle之上的任何異步等待的基于task的選擇:

public static Task WaitOneAsync(this WaitHandle waitHandle) {if (waitHandle == null) throw new ArgumentNullException("waitHandle");var tcs = new TaskCompletionSource<bool>();var rwh = ThreadPool.RegisterWaitForSingleObject(waitHandle, delegate { tcs.TrySetResult(true); }, null, -1, true);var t = tcs.Task;t.ContinueWith(_ => rwh.Unregister(null));return t; }

使用那些之前演示的構(gòu)建于Task之上的數(shù)據(jù)結(jié)構(gòu)的技巧,相似地,構(gòu)建一個不依賴WaitHandles且完全以Task的角度工作的異步信號燈(semaphore)也是可能的。事實(shí)上,.Net 4.5中的SemaphoreSlim 類型暴露了開啟這個的WaitAsync方法。

比如,之前提到的System.Threading.Tasks.Dataflow.dll中的BufferBlock<T>類型可以這樣使用:

static SemaphoreSlim m_throttle = new SemaphoreSlim(N, N);static async Task DoOperation() {await m_throttle.WaitAsync();… // do work m_throttle.Release (); }

從Tasks到WaitHandlers

如之前提到的,Task類實(shí)現(xiàn)了IAsyncResult,該IAsyncResult的實(shí)現(xiàn)暴露了一個返回WaitHandle的AsycnWaitHandle屬性,此WaitHandle是在Task完成時設(shè)置的。照這樣,獲得一個Task的WaitHandle可以像下面這樣實(shí)現(xiàn):

WaitHandle wh = ((IAsyncResult)task).AsyncWaitHandle;

?

返回該系列目錄《基于Task的異步模式--全面介紹》


總結(jié)

以上是生活随笔為你收集整理的与其他.Net异步模式和类型进行互操作的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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