文主要說明ABP中後臺工做者模塊(BackgroundWorker)的實現方式,和後臺工做模塊(BackgroundJob)。ABP經過BackgroundWorkerManager來管理BackgroundJobManager,而後經過BackgroundJobManager來管理BackgroundJob。BackgroundJob就表明一個真正的後臺任務。html
這兩個模塊是在ABPKernelModule的PostInitialize完成初始化的。數據庫
後臺工做者模塊設計模式
首先瀏覽下後臺工做者模塊所涉及到的接口和類。其中BackgroundJobManager屬於後臺工做模塊。其繼承自後臺工做者模塊中的PeriodicBackgroundWorkerBase。框架
逐個分析這些類和接口源碼分析
IRunnable/RunnableBase: 定義了啓動/終止一個任務的方法的接口和基本實現。共三個方法:start, stop, waittostop. start和stop這兩個方法很容易理解,就是啓動和終止一個任務。後文再解釋waittostop方法。spa
IBackgroundWorker:沒有添加任何新方法,這個接口僅用於標識其對應的實現是一個後臺工做任務類,用於在後臺執行一些任務。線程
BackgroundWorkerBase:實現IBackgroundWorker的一個抽象類,同時添加了UOW,Setting 和本地化的一些輔助方法。設計
IBackgroundWorkerManager/BackgroundWorkerManager: 用於管理後臺工做任務 - IBackgroundWorker實例(添加IBackgroundWorker實例到管理器,啓動,終止和註銷後臺任務)。設計一個***Manager接口和類是ABP中設計各個功能塊的慣用思路,起到了對外隱藏實現細節的做用,能夠認爲是Facade設計模式的運用。3d
PeriodicBackgroundWorkerBase:經過封裝AbpTimer實現定時啓動執行任務的功能。這個類型定義個一個抽象方法DoWork. AbpTimer最終會定時執行這個方法。orm
AbpTimer是整個ABP框架實現後臺工做的核心類,其實現原理就是經過一個CLR中的timer定時啓動執行任務。這裏有兩個要點值得留意:
第一,用timer有一個弊端,就是當timer間隔時間內,任務若是沒執行完,timer就會新建一個線程,從頭開始執行這個任務,而上一個線程仍然繼續執行,這樣就會致使系統中產生的線程過多,一下子系統的資源就耗盡了。ABP的解決思路是在執行真正的業務方法以前,經過將timer的duetime設爲無限大,從而timer就失效了。業務方法執行完之後在恢復timer的設置。
第二,如何知道一個Timer真正結束了呢?也就是說如何知道一個Timer要執行的任務已經完成(這裏定義爲A效果),同時timer已失效(這裏定義爲B效果)?ABP經過stop方法實現B,經過WaitToStop實現A效果。WaitToStop會一直阻塞調用他的線程直到_performingTasks變成false,也就是說Timer要執行的任務已經完成(任務完成時會將_performingTasks設爲False,而且釋放鎖)。
後臺工做模塊
首先瀏覽下涉及到的接口和類。
BackgroundJobInfo: 用於持久化job信息的實體類,對應於數據庫中的表AbpBackgroundJobs。這個實體類有如下屬性。一個job對應一個要執行的任務。他又兩個很關鍵的屬性JobArgs和JobType。其JobType就是接下來要介紹的IBackgroundJob實例的類型。IBackgroundJobManager最終就是根據這個JobType經過反射恢復出IBackgroundJob實例的。JobArgs就是傳入IBackgroundJob實例的Execute方法的實參(這裏會被序列化後在賦值給BackgroundJobInfo)。
IBackgroundJob/BackgroundJob:定義一個後臺工做任務的接口/和基本實現。具體的後臺任務類可從BackgroundJob繼承,這是定義最終須要被執行的邏輯的地方。
IBackgroundJobConfiguration/BackgroundJobConfiguration: 配置是否激活後臺工做任務功能。
BackgroundJobPriority:後臺job的優先級
IBackgroundJobStore/InMemoryBackgroundJobStore: 用於持久化後臺任務BackgroundJobInfo。能夠實現這個接口將後臺任務BackgroundJobInfo存儲到數據庫。或者你能夠使用module-zero,它已經實現了IBackgroundJobStore。若是你正在使用第三方的工做管理者(像Hangfire),那麼不須要實現IBackgroundJobStore。
IBackgroundJobManager/BackgroundJobManager, IBackgroundJobManager默認是由BackgroundJobManager實現的。它能夠被其餘的後臺工做提供者替代(Hangfire)。 BackgroundJobManager之因此能在後臺執行任務,是由於其繼承了PeriodicBackgroundWorkerBase基類,並重寫了DoWork方法。
BackgroundJobManager:是PeriodicBackgroundWorkerBase一個派生類,其具體實現了DoWork方法:從BackgroundJobStore(能夠自定義實現從數據庫中讀取)取最多1000個BackgroundJobInfo,而後反射執行BackgroundJobInfo中定義的任務。
下面是一個ABP中經過BackgroundJobManager安排BackgroundJob的例子。