最近项目中需要用到后台Job,原有在Windows中我们会使用命令行程序结合计划任务或者直接生成Windows Service,现在.Net Core跨平台了,虽然Linux下也有计划任务,但跟原有方式一样,没撒图形界面,执行结果之类的只能去服务器查看日志。

看了下Hangfire,基本满足于现有需求,有图形UI,注册后台Job也非常简便,考虑之下,就是用它了。

安装注册

Hangfire的使用也非常简单,在项目中先安装Hangfire包:

PM> Install-Package Hangfire

Asp.Net Core项目的话,打开Startup.cs,在ConfigureServices方法中添加注册:

services.AddHangfire(x => x.UseSqlServerStorage("connection string"));

connection string是数据库连接字符串,我用的时Sql Server,你也可以使用Redis,Mysql等其他数据库。

注册完成后,我们在Configure方法中,添加如下代码:

app.UseHangfireServer();
app.UseHangfireDashboard();

好了,等项目启动之后,Hangfire先Migration相关数据结构,项目启动之后,可以通过项目地址+/Hangfire查看是否运行成功,看到如下界面基本没有问题了。

基本使用

Hangfire的使用非常简单,基本上使用以下几个静态方法:

//执行后台脚本,仅执行一次
BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!")); //延迟执行后台脚本呢,仅执行一次
BackgroundJob.Schedule(
() => Console.WriteLine("Delayed!"),
TimeSpan.FromDays(7)); //周期性任务
RecurringJob.AddOrUpdate(
() => Console.WriteLine("Recurring!"),
Cron.Daily); //等上一任务完成后执行
BackgroundJob.ContinueWith(
jobId, //上一个任务的jobid
() => Console.WriteLine("Continuation!"));

依赖注入

在.Net Core中处处是DI,一不小心,你会发现你在使用Hangfire的时候会遇到各种问题,比如下列代码:

public class HomeController : Controller
{
private ILogger<HomeController> _logger;
public HomeController(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<HomeController>();
}
public IActionResult Index()
{
_logger.LogInformation("start index");
BackgroundJob.Enqueue(() => _logger.LogInformation("this a job!"));
return View();
} }

项目启动后,你能正常访问,但在Hangfire后台你会看到如下错误:



错误信息呢大概意思是不能使用接口或者抽象方法类,其实就是因为Hangfire没有找到实例,那如何让Hangfire支持DI呢?

我们先创建一个MyActivator类,使其继承Hangfire.JobActivator类,代码如下:

public class MyActivator : Hangfire.JobActivator
{
private readonly IServiceProvider _serviceProvider;
public MyActivator(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; public override object ActivateJob(Type jobType)
{
return _serviceProvider.GetService(jobType);
}
}

重写了ActivateJob方法,使其返回的类型从我们的IServiceProvider中获取。

我们试着写两个后台脚本,CheckService和TimerService,CheckService的Check方法在执行计划时,会再次调用Hangfire来定时启动TimerService:

CheckService:

public interface ICheckService
{
void Check();
}
public class CheckService : ICheckService
{
private readonly ILogger<CheckService> _logger;
private ITimerService _timeservice;
public CheckService(ILoggerFactory loggerFactory,
ITimerService timerService)
{
_logger = loggerFactory.CreateLogger<CheckService>();
_timeservice = timerService;
} public void Check()
{
_logger.LogInformation($"check service start checking, now is {DateTime.Now}");
BackgroundJob.Schedule(() => _timeservice.Timer(), TimeSpan.FromMilliseconds(30));
_logger.LogInformation($"check is end, now is {DateTime.Now}");
}
}

TimerService:

public interface ITimerService
{
void Timer();
}
public class TimerService : ITimerService
{
private readonly ILogger<TimerService> _logger;
public TimerService(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<TimerService>();
}
public void Timer()
{
_logger.LogInformation($"timer service is starting, now is {DateTime.Now}");
_logger.LogWarning("timering");
_logger.LogInformation($"timer is end, now is {DateTime.Now}");
}
}

目前还无法使用,我们必须在Startup中注册这2个service:

services.AddScoped<ITimerService, TimerService>();
services.AddScoped<ICheckService, CheckService>();

我们在HomeController修改以下:

public IActionResult Index()
{
_logger.LogInformation("start index");
BackgroundJob.Enqueue<ICheckService>(c => c.Check());
return View();
}

好,一切就绪,只差覆盖原始的Activator了,我们可以在Startup.cs中的Configure方法中使用如下代码:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
GlobalConfiguration.Configuration.UseActivator<MyActivator>(new MyActivator(serviceProvider));
……
……
}

默认情况下Configure方法时没有IServiceProvider参数的,请手动添加

再次启动,我们的Job就会成功执行,截图如下:

参考资料

在Asp.Net Core中使用DI的方式使用Hangfire构建后台执行脚本的更多相关文章

  1. 浅谈ASP.NET Core中的DI

    DI的一些事 传送门马丁大叔的文章 什么是依赖注入(DI: Dependency Injection)?     依赖注入(DI)是一种面向对象的软件设计模式,主要是帮助开发人员开发出松耦合的应用程序 ...

  2. asp.net core 中灵活的配置方式

    asp.net core支持外部文件和命令行参数方式来配置系统运行所需要的配置信息,我们从下面两个常用场景来具体说下具体使用方法. 一.监听地址及端口配置 1,命令行方式 asp.net core系统 ...

  3. ASP.NET Core中的OWASP Top 10 十大风险-跨站点脚本攻击 (XSS)

    不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: https://dotnetcoretutorials.com/201 ...

  4. Asp.Net Core中HttpClient的使用方式

    在.Net Core应用开发中,调用第三方接口也是常有的事情,HttpClient使用人数.使用频率算是最高的一种了,在.Net Core中,HttpClient的使用方式随着版本的升级也发生了一些变 ...

  5. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

  6. ASP.NET Core 中的依赖注入 [共7篇]

    一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了 ...

  7. 在ASP.NET Core中构建路由的5种方法

    原文链接 :https://stormpath.com/blog/routing-in-asp-net-core 在ASP.NET Core中构建路由的5种方法 原文链接 :https://storm ...

  8. C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法

    C#调用接口注意要点   在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...

  9. ASP.NET Core中Middleware的使用

    https://www.cnblogs.com/shenba/p/6361311.html   ASP.NET 5中Middleware的基本用法 在ASP.NET 5里面引入了OWIN的概念,大致意 ...

随机推荐

  1. spring-boot-2.0.3源码篇 - pageHelper分页,绝对有值得你看的地方

    前言 开心一刻 说实话,作为一个宅男,每次被淘宝上的雄性店主追着喊亲,亲,亲,这感觉真是恶心透顶,好像被强吻一样.........更烦的是我每次为了省钱,还得用个女号,跟那些店主说:“哥哥包邮嘛么叽. ...

  2. demo_1

    我练习的demo是基于SSM+MySQL+Eclipse+Tomcat8+Maven3实现的: 创建项目 ## 创建Maven Project: Artifact Id: cn.com.demo    ...

  3. .NET: 谈谈C#中的扩展方法

    扩展方法(Extension Methods)是C#3.0时引入的新特性,相信很多人都听过并且也都用过,最常见的是在LINQ中的使用. 不仅如此,在开发中,我们也可以创建自己扩展方法,使用它来优化类的 ...

  4. .NET Core Cache [MemoryCache]

    参考资料:long0801的博客.MemoryCache微软官方文档 添加对Microsoft.Extensions.Caching.Memory命名空间的引用,它提供了.NET Core默认实现的M ...

  5. 你必须知道的.net读书笔记第四回:后来居上:class和struct

     基本概念 1.1. 什么是class? class(类)是面向对象编程的基本概念,是一种自定义数据结构类型,通常包含字段.属性.方法.属性.构造函数.索引器.操作符等.因为是基本的概念,所以不必在此 ...

  6. c#调用com组件,程序 发生意外<hr=0x80020009>

    引用dll,确认dll没有问题,版本正确,可是一直报发生意外,没有任何其他提示. 解决方案: 看dll引用选项配置 复制到本地:设为true,我的就是false; 嵌入互操作类型:false,如果是t ...

  7. 预计2019年发布的Vue3.0到底有什么不一样的地方?

    摘要: Vue 3.0预览. 原文:预计今年发布的Vue3.0到底有什么不一样的地方? 作者:小肆 微信公众号:技术放肆聊 Fundebug经授权转载,版权归原作者所有. 还有几个月距离 vue2 的 ...

  8. css transition 实现滑入滑出

    transition是css最简单的动画. 通常当一个div属性变化时,我们会立即看的变化,从旧样式到新样式是一瞬间的,嗖嗖嗖!!! 但是,如果我希望是慢慢的从一种状态,转变成另外一种状态,怎么办?  ...

  9. 第五课 Css3旋转放大属性,正六边形的绘制

    ---恢复内容开始--- 一.效果 二.知识点 1.background-color: rgba(0,0,0,.4);   (红色.绿色.蓝色.透明度(0-1)) 2.position: absolu ...

  10. 《Pro Asp.net core mvc 2》bower问题

    在阅读<Pro Asp.net core mvc 2>中有使用bower管理包,可能是由于vs2017或者bootstrap什么地方改变了,按照步骤进行操作,完全没有对应的样式出现.开始以 ...