<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ā)編程-反應(yīng)式編程

          共 4045字,需瀏覽 9分鐘

           ·

          2021-03-11 00:43

          寫(xiě)給普通:

          你以為我沒(méi)回頭

          我以為你沒(méi)挽留

          年輕的想法還是盡早安排落地

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

          本小節(jié)開(kāi)始學(xué)習(xí)反應(yīng)式編程,以及在.NET中數(shù)據(jù)并行的實(shí)現(xiàn)方式。本系列保證最少代碼呈現(xiàn)量,雖然talk is cheap, show me the code被奉為圭臬,我的學(xué)習(xí)習(xí)慣是,只學(xué)習(xí)知識(shí)點(diǎn),代碼不在當(dāng)下立馬要用的時(shí)候不會(huì)認(rèn)真去讀的,更何況在大多時(shí)候在手機(jī)閱讀更不順暢。


          反應(yīng)式編程


          就是將事件作為數(shù)據(jù)流異步地監(jiān)聽(tīng)和處理的一種編程范式。類(lèi)似編輯Excel表格時(shí),某個(gè)單個(gè)元的值是由其他單元格值決定的公式,一旦其他單元格的值發(fā)生變化,此公式單個(gè)格也會(huì)隨之更新。


          如果以聲明式描述操作,那么就是函數(shù)式反應(yīng)型編程。


          反應(yīng)式編程的好處就是通過(guò)描述一種簡(jiǎn)單且可維護(hù)的方法來(lái)處理異步、無(wú)阻賽計(jì)算和IO,從而增加了對(duì)多核和多CPU硬件上計(jì)算資源的使用。事件的控制從“請(qǐng)求”變?yōu)榱恕暗却薄4髷?shù)據(jù)實(shí)時(shí)流處理環(huán)境,都會(huì)使用到反應(yīng)式編程,例如推文系統(tǒng)處理,日志系統(tǒng)收集等。


          .NET中的工具


          .NET中是有基于委托的模型事件的。訂閱者的事件處理程序注冊(cè)一系列事件,并在調(diào)用時(shí)觸發(fā)事件。類(lèi)似桌面應(yīng)用程序中經(jīng)常使用Button的Click事件,通過(guò)使用+=來(lái)注冊(cè)綁定事件。所以傳統(tǒng)意義上的事件就是來(lái)處理GUI用戶(hù)界面的交互。這種命令式編程難以處理多個(gè)復(fù)雜事件的編排,并且容易造成內(nèi)存泄漏。


          在F#中使用|>管道操作符可以連接多個(gè)事件。不熟悉F#,就不多做說(shuō)明。主要看看C#如果處理。


          Reactive Extensions(Rx)反應(yīng)式擴(kuò)展


          LINQ 是 對(duì) 序 列 數(shù) 據(jù) 進(jìn) 行 查 詢(xún) 的 一 系 列 語(yǔ) 言 功 能。 內(nèi) 置 的 LINQ to Objects( 基 于 IEnumerable<T>) 和 LINQ to Entities( 基 于 IQueryable<T>) 是 兩 個(gè) 最 常 用 的 LINQ 提 供 者。另外還有很多提供者,并且大多數(shù)都采用相同的基本架構(gòu)。查詢(xún)是延后執(zhí)行的,只有在需要時(shí)才會(huì)從序列中獲取數(shù)據(jù)。從概念上講,這是一種拉取模式。 在查詢(xún)過(guò)程中數(shù)據(jù)項(xiàng)是被逐個(gè)拉取出來(lái)的。


          Reactive Extensions(Rx)把事件看作是依次到達(dá)的數(shù)據(jù)序列。因此,將 Rx 認(rèn)作是 LINQ to events( 基 于 IObservable<T>) 也 是 可 以 的, 它 與 其 他 LINQ 提 供 者 的 主 要 區(qū) 別 在 于, Rx 采用“推送”模式。就是說(shuō),Rx 的查詢(xún)規(guī)定了在事件到達(dá)時(shí)程序該如何響應(yīng)。Rx 在 LINQ 的基礎(chǔ)上構(gòu)建,增加了一些功能強(qiáng)大的操作符,作為擴(kuò)展方法。


          通過(guò)nuget安裝Rx 



          Observable和Enumerable是對(duì)偶存在,很多方法相似可以相互轉(zhuǎn)換。像下面輸出結(jié)果都是1-5,。


          // Observable對(duì)象Observable.Range(1, 5)  .Subscribe(x => Console.WriteLine(x)); // Enumerable對(duì)象foreach (var x in Enumerable.Range(1, 5))  Console.WriteLine(x);


          Rx里主要的接口有兩個(gè),IObervable<T>和 IObserver<T>,上面Observable遍歷輸出只是簡(jiǎn)化了IObserver對(duì)象的創(chuàng)建,Subscribe方法可以只傳入OnNext委托,也可以傳入完整的IObserver對(duì)象。

          public interface IObservable<out T>{  IDisposable Subscribe(IObserver<T> observer);} public interface IObserver<in T>{  void OnCompleted();  void OnError(Exception error);  void OnNext(T value);}
          var observer = Observer.Create<int>( x => Console.WriteLine(x), // onNext參數(shù)(delegate) ex => { throw ex; }, // onError參數(shù)(delegate) () => { }); // onCompleted參數(shù)(delegate) Observable.Range(1, 5).Subscribe(observer);


          Rx主要用處


          Rx的有點(diǎn)主要在于能夠?qū)鹘y(tǒng)的異步編程方式從支離破碎的代碼調(diào)用中解放出來(lái),將各個(gè)事件的處理連接起來(lái)放在一個(gè)單獨(dú)的方法中,增加代碼可讀和可維護(hù)。


          GUI編程中合并事件

          桌面編程中多個(gè)事件進(jìn)行組合的情況,比如鼠標(biāo)按下/移動(dòng)/放開(kāi)事件進(jìn)行關(guān)聯(lián)處理,一般可能需要定一個(gè)變量Flag來(lái)標(biāo)記狀態(tài),管理比較混亂。Rx可以將它們合成一個(gè)事件。


          var drag = from down in this.MouseDownAsObservable()                       from move in this.MouseMoveAsObservable().TakeUntil(this.MouseUpAsObservable())                       select new { move.X, move.Y };


          // 利用擴(kuò)展方法將Winform原有的事件變換為 IObservable<T> 對(duì)象    public static class FormExtensions    {        public static IObservable<MouseEventArgs> MouseMoveAsObservable(this Form form)        {            return Observable.FromEventPattern<MouseEventArgs>(form, "MouseMove").Select(e => e.EventArgs);        }
          public static IObservable<MouseEventArgs> MouseDownAsObservable(this Form form) { return Observable.FromEventPattern<MouseEventArgs>(form, "MouseDown").Select(e => e.EventArgs); }
          public static IObservable<MouseEventArgs> MouseUpAsObservable(this Form form) { return Observable.FromEventPattern<MouseEventArgs>(form, "MouseUp").Select(e => e.EventArgs); } }


          Timer通知事件


          在一定的時(shí)間間隔監(jiān)視某個(gè)值的場(chǎng)景。下面例子中就是每隔5s檢查textbox值是否變化,變化了就更新label。比以往簡(jiǎn)介了很多


          // 每隔1秒監(jiān)視一下watchTarget.Value的值var polling =  Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(5))  .Select(_ => textBox1.Text)  .DistinctUntilChanged(); // 只有在值發(fā)生變化時(shí)才引發(fā)事件(polling)polling.Subscribe(msg => this.Invoke(new Action<string>((e) => this.label1.Text = e),msg));


          先這樣草草結(jié)束吧,用到了再去詳細(xì)研究下。像Rx是以往沒(méi)聽(tīng)過(guò)的概念,有些場(chǎng)景中確實(shí)好用,但習(xí)慣了以往的方式,也比較難嘗試,慢慢破圈慢慢生成吧。



              to be contiued!
          下集:任務(wù)異步模型

          今天報(bào)名增駕了三輪摩托車(chē),準(zhǔn)備過(guò)一把騎士的癮,客官老爺們有摩友的,可以交流交流
          (* ̄︶ ̄)



          寫(xiě)給普通:

          你以為我沒(méi)回頭

          我以為你沒(méi)挽留

          年輕的想法還是盡早安排落地



          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  狠狠色婷婷 | 亚洲无码草逼逼 | 欧美一卡二卡三卡四卡视频区 | 韩国一区二区三区 | 久久精品大香蕉 |