前文寫了關於C#中的非同步程式設計。後台有無數人在討論,很多人把非同步和多執行緒混了。
文章在這兒:一文說通C#中的非同步程式設計
所以,本文從體系的角度,再寫一下這個非同步程式設計。
?
一、C#中的非同步程式設計演變
1. 非同步程式設計模型
這是C#中早期的非同步模型,透過
實現的程式碼大體是這個樣子:
1 | class MyClass<br>{<!-- --><br> IAsyncResult BeginAction(para ..., AsyncCallback callback, object state);<br> T EndAction(IAsyncResult async_result);<br>}<br> |
這種方式在一些庫里還有保留,像
程式設計時,不建議用這種方式。
2. 基於事件的非同步模型
這是C#中間一個轉場時期的非同步模型,核心是基於一個或多個事件、事件處理委派的衍生類別型,是一種使用多執行緒的模式。
這個模式在類別庫里,多用在Winform/WPF中的套件的事件處理,你可以隨便拿一個Framework 4.5以前的套件去研究,大多數都是這種方式。
這種方式的實現大體是這個樣子:
1 | class MyClass<br>{<!-- --><br> void ActionAsync(para ...);<br> event ActionCompletedEventHandler action_completed;<br>}<br> |
這種方式使用多執行緒,所以,它具有多執行緒的全部特點和要求。
從微軟的建議來看,Framework 4.5以後,並不推薦使用這種模式。
3. 基於任務的非同步模型
這種非同步模型從Framework 4.0以後引入,使用單一方法來表示非同步的開始和完成。這是目前推薦的非同步開發方式。在上個文章中的非同步模式,就是這個方式。
這個方式的程式碼實現是這樣的:
1 | class MyClass<br>{<!-- --><br> Task<T> ActionAsync(para ...);<br>}<br> |
?
我們所說的非同步,包括前文講的非同步,全部是基於這個基於任務的非同步模型來討論。
在這個模型下,前文說過,非同步不是多執行緒。今天再強調一遍,非同步不僅不是多執行緒,同時非同步也不一定會使用多執行緒。
為了防止不提供原網址的轉載,特在這裡加上原文連結:https://www.cnblogs.com/tiger-wang/p/13428372.html
二、非同步模型中的「任務」
先來看看任務:
這個「任務」,是一種「承諾」,承諾會在稍後完成任務。
它有兩個關鍵字:
在某些情況下,非同步可以採用多執行緒來實現,這時候,
關於非同步中
三、非同步程式設計的兩種模式
1. 單執行緒模式
先看程式碼:
1 | Task<string> GetHtmlAsync()<br>{<!-- --><br> var client = new HttpClient();<br> var gettask = client.GetStringAsync("https://home.cnblogs.com/u/tiger-wang");<br><br> return await gettask;<br>}<br> |
這種模式下,這個非同步工作於單執行緒狀態。程式碼雖然回傳一個任務
因為執行緒沒有切換,所以也不存在上下文切換的問題。
2. 多執行緒模式
既然
看程式碼:
1 | Task<string> GetHtmlAsync()<br>{<!-- --><br> var gettask = Task.Run(() => {<!-- --><br> var client = new HttpClient();<br> return client.GetStringAsync("https://home.cnblogs.com/u/tiger-wang");<br> });<br><br> return await gettask;<br>}<br> |
對方上一段程式碼,把呼叫
這種方式中,非同步被放到了主執行緒以外的新執行緒中執行,換句話說,這個非同步在以多執行緒的方式執行。
在這種模式下,
四、非同步的兩個額外狀態
1. 取消
非同步針對的是需要耗用長時間執行的工作。在工作過程中,如果需要,我們可以取消非同步的執行。系統提供了一個類
定義方式:
1 | Task<T> ActionAsync(para ..., CancellationToken cancellationtoken);<br> |
呼叫方式:
1 | CancellationTokenSource source = new CancellationTokenSource();<br>CancellationToken cancel_token = source.Token;<br><br>await ActionAsync(para, cancel_token);<br> |
需要取消時:
1 | source.Cancel();<br> |
就可以了。
在做API時,非同步中加個
2. 進度
長時間執行,如果能給出個進度也不錯。
定義方式:
1 | Task<T> ActionAsync(para ..., IProgress<T> progress);<br> |
其中,T是需要回傳的進度值,可以是各種需要的型別。
當然,我們需要實現IProgress:
1 | public class Progress<T> : IProgress<T> <br>{ <br> public Progress(); <br> public Progress(Action<T> handler); <br> protected virtual void OnReport(T value); <br> public event EventHandler<T> ProgressChanged; <br>} <br> |
?
全文完。
?
這篇文章是對前一篇文章的補充和擴展。所以,要兩篇一起看,才更好。
一文說通C#中的非同步程式設計
微信公眾號:老王Plus 掃描二維碼,關注個人公眾號,可以第一時間得到最新的個人文章和內容推送 本文版權歸作者所有,轉載請保留此宣告和原文連結 |