后台任务
比较耗时的需求可以这样解决
后台工作(Background job)
1.创建一个后台job
public class TestJob : BackgroundJob<int>, ITransientDependency {
[UnitOfWork] public override void Execute(int number) { Logger.Debug(number.ToString()); } }
可以注入并使用 IBackgroundJobManager将作业添加到队列中
public class MyService { private readonly IBackgroundJobManager _backgroundJobManager; public MyService(IBackgroundJobManager backgroundJobManager) { _backgroundJobManager = backgroundJobManager; } public void Test() { _backgroundJobManager.Enqueue<TestJob, int>(42); } }
通过MyService调用 在其他Task接口中 调用Test() 有时候会出现当前作业执行失败的情况 不清楚为什么
public class MyServiceAppService : ApplicationService, IMyServiceAppService { private readonly IBackgroundJobManager _backgroundJobManager; public MyServiceAppService(IBackgroundJobManager backgroundJobManager) { this._backgroundJobManager = backgroundJobManager; } public void SendJob() { MyService myService = new MyService(_backgroundJobManager); myService.Test(); } public async Task SendJobAsync() { MyService myService = new MyService(_backgroundJobManager); myService.Test(); await Task.FromResult(0); } }
*********************
后台工作者(Background workers)
它们是在后台运行的应用程序中的简单 独立线程。通常,它们会定期运行以执行某些任务
1.创建后台定时运行任务
public class MakeInactiveUsersPassiveWorker : PeriodicBackgroundWorkerBase, ISingletonDependency { private readonly IRepository<Customer, Guid> _customerRepository; public MakeInactiveUsersPassiveWorker(AbpTimer timer, IRepository<Customer, Guid> customerRepository ) : base(timer) { _userRepository = userRepository; Timer.Period = 5000; //5 seconds (good for tests, but normally will be more) } [UnitOfWork] protected override void DoWork() { //using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant)) //{var inactiveUsers = _customerRepository.GetAll().IgnoreQueryFilters().Where(t => t.IsSystem != true).ToList(); foreach (var inactiveUser in inactiveUsers) { Logger.Info(inactiveUser.Name + " :这个用户不是系统创建的"); } Logger.Info( " :这个用户不是系统创建的"); CurrentUnitOfWork.SaveChanges(); //} } }
2.在模块的预初始化中注册
public override void PostInitialize() { var workManager = IocManager.Resolve<IBackgroundWorkerManager>(); workManager.Add(IocManager.Resolve<MakeInactiveUsersPassiveWorker>()); }
3.注意: 这个后台工作者中注入了_customerRepository这个仓储 所以在模块的预初始化中解析MakeInactiveUsersPassiveWorker需要在注入仓储之后 , 后台工作者在application和code的module中注入是无效的 因为这两个模块的时候还没有注入仓储 可以考虑把这两行代码放在Web.Core的初始化方法中或者其他地方
**************************
通过Hangfire替换ABP默认后台作业管理器
1.安装
Abp.HangFire.AspNetCore Hangfire.SqlServer
2.更改Startup类以将Hangfire添加到依赖项注入,然后在ConfigureServices方法中配置存储和连接字符串 :
services.AddHangfire(config => { config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default")); });
3.然后,我们在Configure方法中添加UseHangfireServer调用:
app.UseHangfireServer();
启动仪表盘
app.UseHangfireDashboard("/hangfire", new DashboardOptions { //Authorization = new[] { new AbpHangfireAuthorizationFilter("MyHangFireDashboardPermissionName") } });
4.配置我们的Web模块来替换ABP的默认后台作业管理器的Hangfire:
[DependsOn(typeof (AbpHangfireAspNetCoreModule))] public class MyProjectWebModule : AbpModule { public override void PreInitialize() { Configuration.BackgroundJobs.UseHangfire(); } //... }
5.如果报错
检查上面两个安装的包的版本 安装这两个包版本对不上没有自动抛异常 需要自己手动检查
所有的后台任务会在/Hangfire展示
后台任务 在ABP模块进行初始化的时候 会初始化一个后台JOB对象放到workerManager 中 workerManager这个对象里面就是存放后台job对象和所有的后台工作者对象
var workerManager = IocManager.Resolve<IBackgroundWorkerManager>(); workerManager.Start(); workerManager.Add(IocManager.Resolve<IBackgroundJobManager>()); }
后台任务和后台工作者最后都会包成一个PeriodicBackgroundWorkerBase对象 定时的执行周期任务都是通过.net下的Timer对象来实现 ABP包了一层AbpTimer 解决第一次任务未执行完毕 第二次任务就启动的问题
ABP在执行当前后台任务的时候 会把执行周期设置为无限大 等执行完毕 在把执行周期置为用户设定的时间(确保执行第二次后台任务,第一次已经执行完毕)
在BackgroundJobManager中的DoWork()方法中就是根据条件获取后台job任务 执行包装好的业务代码
后台任务最后会转成一个PeriodicBackgroundWorkerBase对象 默认周期5秒钟
后台工作者 需要自己在module中注册到workerManager 中 每一个后台工作者都是一个单独的线程