文主要说明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的例子。