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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

事件驱动之异步事件

發布時間:2024/9/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 事件驱动之异步事件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

上一篇講了事件,以及為什么要使用事件,主要是為了解耦,但是有同學就問了,同步如果訂閱事件的人太多,比如13億人都關心上頭條的事,那么RaiseEvent得等13億人都處理完,那得多久呀,從此再也不敢發事件了。 舉個例子,你在網上下單,下完單要通知庫房,甚至要通知供應商補貨,如果都是同步的話,消費者還不等急死呀,實際上你在電商網站上下個單, 一般你很快就能到訂單頁面,那個頁面告訴你:“兄弟,訂單已經創建成功,訂單號是xxxxx-xxxxx-xxxx-xxxx,你的訂單已經提交到庫房” 等。然后你就很快了的下另一單了。好吧, 提問的同學,說好的妹子呢?

實現思路

發出事件

public void Head() { var NewsPaper = new NewsPaper("南都娛樂"); NewsPaper.WriteToHeader("汪峰"); RaiseEvent(new HeadedEvent {Name = "汪峰"}); } private void RaiseEvent(HeadedEvent headedEvent) { EventBus.Publish<HeadedEvent>(new HeadedEvent { Name = "汪峰" }); }

所以我們只需在代碼里RaiseEvent就可以了。

訂閱事件

其實很簡單,因為我們要實現的是同步的事件,我們只需要找到所有處理這個事件的實現類,然后調用所有就可以了。

public interface IEventHandler<TEvent> where TEvent : Event {void Handle(TEvent e); } public class HeadedEvent:Event { public string Name { get; set; } } public class GuoJiZhangMotherEventHandler : IEventHandler<HeadedEvent> { public void Handle(HeadedEvent e) { Console.WriteLine(e.Name+", Are you kidding me?"); } } public class PiMingEventHandler:IEventHandler<HeadedEvent> { public void Handle(HeadedEvent e) { Console.WriteLine(e.Name+", Guo Ji Zhang is your last wife?"); } }

我們可以看到正真的事件協調者是EventBus, 之前的代碼如下是同步的。

public class EventBus {public static void Publish<T>(T concreteEvent) where T: Event { var handlers = _container.ResolveAll<IEventHandler<T>>(); foreach (var handle in handlers) { handle.Handle(concreteEvent); } } }

為了提高性能,我們可以先來第一步改進

publicvoid Publish<T>(T @event) where T : Event{var handlers = _eventHandlerFactory.GetHandlers<T>();handlers.AsParallel().ForAll((h)=> h.Handle(@event)); }

我們可以看到,現在并行處理可以大大加快速度,但是有兩個問題,第一個問題就是沒有處理異常,所以讓我們加上異常。

public void Publish<T>(T @event) where T : Event{var handlers = _eventHandlerFactory.GetHandlers<T>(); handlers.AsParallel().ForAll((h)=> HandleEvent<T>(h,@event)); } private void HandleEvent<T>(IEventHandler<T> handle, T @event) where T : Event { try { handle.Handle(@event); } catch (Exception e) { // Log the exception, as the caller don't care this } } }

第二個問題,就是我們雖然用了并行加快了速度,但是還沒有正真實現異步,整個程序還是等所有Handler處理完才返回。

publicvoid Publish<T>(T @event) where T : Event{var handlers = _eventHandlerFactory.GetHandlers<T>();handlers.Select(h => Task.Factory.StartNew(() => HandleEvent<T>(h, @event))); }

這段代碼執行完,盡然發現Handler沒有執行,好吧,原因是IQueryable的延遲執行,所以我們需要調用一下ToList

publicvoid Publish<T>(T @event) where T : Event{var handlers = _eventHandlerFactory.GetHandlers<T>();handlers.Select(h => Task.Factory.StartNew(() => HandleEvent<T>(h, @event))).ToArray(); }

好了,我們就這樣輕易的實現了一個AsyncEventBus, 是不是感謝.Net的強大?

總結

這里還只是一個系統內部的Async, 如果涉及到系統之間的交互,這個就不行了,而且如果異步處理有錯誤,我們就會有信息丟失,所以需要更健壯的異步事件處理系統,這個后面再講,但是一般的系統我們只需要把出錯的時間記錄下來,然后再看要不要處理就可以。

另外,異步要處理的東西很多,比如處理完畢后,如何通知用戶,還是讓用戶刷新? 我個人建議,一般情況下都不要用異步,只有在真的需要的時候再用。

  • 作者: 王德水
  • 出處:http://deshui.wang

總結

以上是生活随笔為你收集整理的事件驱动之异步事件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。