文主要说明ABP中后台工作者模块(BackgroundWorker)的实现方式,和后台工作模块(BackgroundJob)。ABP通过BackgroundWorkerManager来管理BackgroundJobManager,然后通过BackgroundJobManager来管理BackgroundJob。BackgroundJob就代表一个真正的后台任务。

这两个模块是在ABPKernelModule的PostInitialize完成初始化的。

后台工作者模块

首先浏览下后台工作者模块所涉及到的接口和类。其中BackgroundJobManager属于后台工作模块。其继承自后台工作者模块中的PeriodicBackgroundWorkerBase。

逐个分析这些类和接口

IRunnable/RunnableBase: 定义了启动/终止一个任务的方法的接口和基本实现。共三个方法:start, stop, waittostop. start和stop这两个方法很容易理解,就是启动和终止一个任务。后文再解释waittostop方法。

IBackgroundWorker:没有添加任何新方法,这个接口仅用于标识其对应的实现是一个后台工作任务类,用于在后台执行一些任务。

BackgroundWorkerBase:实现IBackgroundWorker的一个抽象类,同时添加了UOW,Setting 和本地化的一些辅助方法。

IBackgroundWorkerManager/BackgroundWorkerManager: 用于管理后台工作任务 - IBackgroundWorker实例(添加IBackgroundWorker实例到管理器,启动,终止和注销后台任务)。设计一个***Manager接口和类是ABP中设计各个功能块的惯用思路,起到了对外隐藏实现细节的作用,可以认为是Facade设计模式的运用。

PeriodicBackgroundWorkerBase:通过封装AbpTimer实现定时启动执行任务的功能。这个类型定义个一个抽象方法DoWork. AbpTimer最终会定时执行这个方法。

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的例子。

返回ABP源码分析系列文章目录

ABP源码分析九:后台工作任务的更多相关文章

  1. [Abp 源码分析]六、工作单元的实现

    0.简介 在 Abp 框架内部实现了工作单元,在这里讲解一下,什么是工作单元? Unit Of Work(工作单元)模式用来维护一个由已经被业务事物修改(增加.删除或更新)的业务对象组成的列表.Uni ...

  2. [Abp 源码分析]九、事件总线

    0.简介 事件总线就是订阅/发布模式的一种实现,本质上事件总线的存在是为了降低耦合而存在的. 从上图可以看到事件由发布者发布到事件总线处理器当中,然后经由事件总线处理器调用订阅者的处理方法,而发布者和 ...

  3. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  4. [Abp 源码分析]十一、权限验证

    0.简介 Abp 本身集成了一套权限验证体系,通过 ASP.NET Core 的过滤器与 Castle 的拦截器进行拦截请求,并进行权限验证.在 Abp 框架内部,权限分为两块,一个是功能(Featu ...

  5. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  6. ABP源码分析十九:Auditing

    审计跟踪(也叫审计日志)是与安全相关的按照时间顺序的记录,它们提供了活动序列的文档证据,这些活动序列可以在任何时间影响一个特定的操作. AuditInfo:定义如下图中需要被Audit的信息. Aud ...

  7. ABP源码分析二十九:ABP.MongoDb

    这个Module通过建立一个MongoDbRepositoryBase<TEntity> 基类,封装了对MongoDb数据库的操作. 这个module通过引用MongoDB.Driver, ...

  8. ABP源码分析三十九:ABP.Hangfire

    ABP对HangFire的集成主要是通过实现IBackgroundJobManager接口的HangfireBackgroundJobManager类完成的. HangfireBackgroundJo ...

  9. [Abp 源码分析]零、文章目录

    0.系列文章目录 一.Abp 框架启动流程分析 二.模块系统 三.依赖注入 四.模块配置 五.系统设置 六.工作单元的实现 七.仓储与 Entity Framework Core 八.缓存管理 九.事 ...

随机推荐

  1. scrapy 知乎用户信息爬虫

    zhihu_spider 此项目的功能是爬取知乎用户信息以及人际拓扑关系,爬虫框架使用scrapy,数据存储使用mongo,下载这些数据感觉也没什么用,就当为大家学习scrapy提供一个例子吧.代码地 ...

  2. ASP.NET Core的路由[2]:路由系统的核心对象——Router

    ASP.NET Core应用中的路由机制实现在RouterMiddleware中间件中,它的目的在于通过路由解析为请求找到一个匹配的处理器,同时将请求携带的数据以路由参数的形式解析出来供后续请求处理流 ...

  3. EventBus实现activity跟fragment交互数据

    最近老是听到技术群里面有人提出需求,activity跟fragment交互数据,或者从一个activity跳转到另外一个activity的fragment,所以我给大家介绍一个开源项目,EventBu ...

  4. C#创建dll类库

    类库让我们的代码可复用,我们只需要在类库中声明变量一次,就能在接下来的过程中无数次地使用,而无需在每次使用前都要声明它.这样一来,就节省了我们的内存空间.而想要在类库添加什么类,还需取决于类库要实现哪 ...

  5. PHP好用但又容易忽略的小知识

    1.PHP函数之判断函数是否存在 当我们创建了自定义函数,并且了解了可变函数的用法,为了确保程序调用的函数是存在的,经常会先使用function_exists判断一下函数是否存在.同样的method_ ...

  6. 内存映射文件MemoryMappedFile使用

    参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...

  7. Android中点击事件的实现方式

    在之前博文中多次使用了点击事件的处理实现,有朋友就问了,发现了很多按钮的点击实现,但有很多博文中使用的实现方式有都不一样,到底是怎么回事.今天我们就汇总一下点击事件的实现方式. 点击事件的实现大致分为 ...

  8. 高仿it之家新闻客户端源码

    仿it之家新闻客户端界面,数据为本地假数据.仅实现了新闻模块的功能. 源码下载:http://code.662p.com/list/11_1.html 详细说明:http://android.662p ...

  9. Topshelf 支持Mono 扩展Topshelf.Linux

    使用Topshelf 5步创建Windows 服务 这篇文章大家可以了解到使用Topshelf可以很好的支持Windows服务的开发,但是它和Mono不兼容,Github上有一个扩展https://g ...

  10. Lesson 24 It could be worse

    Text I entered the hotel manager's office and sat down. I had just lost £50 and I felt very upset. ' ...