<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          .NET并發(fā)編程-異步編程模型上

          共 4366字,需瀏覽 9分鐘

           ·

          2021-03-25 23:20

          寫給普通:

          時間撲面而來,我們終將釋懷

          健康的活著,平靜的過著

          開心的笑著,適當?shù)拿χ?/span>

          本系列學習在.NET中的并發(fā)并行編程模式,實戰(zhàn)技巧

          本小節(jié)開始學習任務編程模型。本系列保證最少代碼呈現(xiàn)量,雖然talk is cheap, show me the code被奉為圭臬,我的學習習慣是,只學習知識點,代碼不在當下立馬要用的時候不會認真去讀的,更何況在大多時候在手機閱讀更不順暢。


          本小節(jié)介紹任務異步模型。作為開發(fā)人員,異步編程是對你技能集的一個重要補充。


          1、異步編程模型APM


          異步(asynchronous)操作是指請求開始不需要等待請求的返回,請求完成后再切換回來,期間可以做其他事情。就是不會閑著等待任何一個操作的完成

          并行主要和應用程序性能有關,它還可以利用現(xiàn)代多核計算機結構,增強對多線程CPU密集型工作,異步是并發(fā)的超集,主要面向I/O密集型操作,而不是CPU密集型操作。異步解決了延遲問題(任何需要很長時間才能運行的問題)。


          2、.NET中的異步支持


          2.1 Begin/End模式


          原始的異步編程模式是將一個長時間運行的函數(shù)分為兩個部分,一部分負責啟動異步操作Begin,另一部分負責完成時回調End,稱之為Begin/End模型。以讀取文件為例的同步和異步編程如下所示


          void ReadFileBlocking(string filePath, Action<byte[]> process){    using (var fileStream = new FileStream(filePath, FileMode.Open,                                  FileAccess.Read, FileShare.Read))    {        byte[] buffer = new byte[fileStream.Length];        int bytesRead = fileStream.Read(buffer, 0, buffer.Length);        process(buffer);    }}
          //以下為異步讀取IAsyncResult ReadFileNoBlocking(string filePath, Action<byte[]> process){ using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 0x1000, FileOptions.Asynchronous)) { byte[] buffer = new byte[fileStream.Length]; var state = Tuple.Create(buffer, fileStream, process); return fileStream.BeginRead(buffer, 0, buffer.Length, EndReadCallback, state); }}
          void EndReadCallback(IAsyncResult ar){ var state = ar.AsyncState as Tuple<byte[], FileStream, Action<byte[]>>; using (state.Item2) state.Item2.EndRead(ar); state.Item3(state.Item1);}


          上面EndReadCallback就是讀取完成后的回調函數(shù),什么是回調,回調是一個用于加快程序速度的函數(shù)。異步編程使用回調創(chuàng)建新的線程來獨立地運行方法。在異步運行時,程序通過一個用于注冊另一個函數(shù)的延續(xù)的可重入函數(shù)來通知調用函數(shù)任何更新,包括失敗、取消、進度和完成。這個過程需要一些時間才能產生結果。


          Begin/End模式,將開始和回調通知分離開,代碼看起來不像順序結構那么順眼。并且像上例state變量一樣,我們需要維護一個狀態(tài)以保證回調函數(shù)能訪問到。


          2.2 基于事件的異步編程


          EAP(Event-based Asynchronous Programming)基于事件的異步編程模式是從.NET2開始引入。用事件代替以往的回調,但仍然不能剝離方法調用和事件處理程序。


          3、基于任務異步編程模型


          TAP模型淘汰了APM和EAP,如果你是C#使用者,建議使用TAP模型。TAP為異步代碼提供了一種干凈的聲明式風格。


          C#5.0開始,對象Task和Task<T>在關鍵字async和await的支持下,已經成為異步操作模型的主要組件。TAP模型只通過純粹關注語法方面就解決了回調問題,從而繞過了推理代碼中表達的事件序列出現(xiàn)的困難。C#5.0中的異步函數(shù)解決了耗費運行時間的延遲問題。


          TAP核心思想就是將異步操作包進一個Task里面。異步執(zhí)行的話,使用async關鍵字通知編譯器該方法異步運行不阻塞。上面讀取文件例子改為TAP模型如下

          async Task ReadFileNoBlockingAsync(string filePath, Func<byte[], Task> process){    using (var fileStream = new FileStream(filePath, FileMode.Open,                                    FileAccess.Read, FileShare.Read, 0x1000,                                    FileOptions.Asynchronous))    {        byte[] buffer = new byte[fileStream.Length];        int bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length);        await process(buffer);    }}


          當運行到await關鍵字時,它會掛起調用方法并將控制權交換給它的調用者,直到所等待的任務完成為止。


          3.1 異步取消


          以下是用于取消Task或異步操作相關的.NET類型:


          • CancellationTokenSource負責創(chuàng)建取消令牌,并向該令牌的所有拷貝發(fā)送取消請求

          • CancellationToken是用于監(jiān)控當前令牌狀態(tài)的結構。


          TAP模型中的取消支持,創(chuàng)建任務時傳遞取消令牌,然后異步操作會檢查令牌的狀態(tài),并在觸發(fā)請求時取消計算。像下面所示:

          CancellationTokenSource cts = new CancellationTokenSource();  // 取消令牌
          async Task<string> DownloadStockHistory(string symbol, CancellationToken token) //傳遞{ string stockUrl = CreateFinanceUrl(symbol); var request = await new HttpClient().GetAsync(stockUrl, token); // 傳遞給方法以得取消 return await request.Content.ReadAsStringAsync();}//cts.Cancel(); // 出發(fā)取消令牌

          或則使用CancellationToken來注冊回調

          CancellationTokenSource tokenSource = new CancellationTokenSource();CancellationToken token = tokenSource.Token;Task.Run(async ()=> {    var webClint = new WebClient();    token.Register(()=>webClint.CancelAsync());    var data = await webClint.DownloadDataTaskAsync(url);},token);


          在之前版本如果沒有async和await時,通過手動檢查取消,定期使用token.ThrowIfCancellationRequested方法檢查取消


          3.2 協(xié)作取消支持


          使用CancellationTokenSource可以輕松創(chuàng)建由多個其他令牌組成的合令牌像下面所示有一個取消原因被觸發(fā)就執(zhí)行取消操作。

          CancellationTokenSource ctsOne = new CancellationTokenSource()CancellationTokenSource ctsTwo = new CancellationTokenSource();CancellationTokenSource ctsComposite =  CancellationTokenSource.CreateLinkedTokenSource(ctsOne.Token,ctsTwo.Token);CancellationToken token = ctsComposite.Token;


          字數(shù)有點超了哈,想要每個小片1k字左右的,剩下的異步重試,錯誤處理放在下小節(jié)吧。


              to be contiued!
          下集:任務異步模型下




          寫給普通:

          時間撲面而來,我們終將釋懷

          健康的活著,平靜的過著

          開心的笑著,適當?shù)拿χ?/span>



          瀏覽 55
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产福利91 | 国产精品久久久婷婷五月 | 成人天堂| 亚洲无 码A片在线观看 | 欧美日韩亚洲国产a |