在 ASP.NET Core 中,后台任务作为托管服务实现.托管服务是一个类,而且必须实现 IHostedService 接口,该接口定义了两个方法:

  • StartAsync(CancellationToken cancellationToken)  该方法包含启动后台任务的逻辑,当启动服务器并触发 IApplicationLifetime.ApplicationStarted 后调用该方法.
  • StopAsync(CancellationToken cancellationToken)主机正常关闭时触发,包含结束后台任务和处理任何非托管资源的逻辑.如果应用意外关闭,则可能不会调用.

托管服务在应用启动时激活一次,在应用关闭时正常关闭.实现 IDisposable 时,可在处置服务容器时处理资源.如果在执行后台任务期间引发错误,即使未调用 StopAsync ,也应调用 Dispose.

示例一:计时的后台任务

    public class TimedHostedService : IHostedService, IDisposable
{ private readonly ILogger _logger;
private Timer _timer;
public TimedHostedService(ILogger<TimedHostedService> logger)
{
_logger = logger;
} public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is starting." + DateTime.Now);
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds());//立即执行一次,每5秒执行一次
return Task.CompletedTask;
} private void DoWork(object state)
{
_logger.LogInformation("Timed Background Service is working." + DateTime.Now);
} public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is stopping." + DateTime.Now);
_timer?.Change(Timeout.Infinite, );//不再执行
return Task.CompletedTask;
} public void Dispose()
{
_timer?.Dispose();
}
}

注册该后台任务:

        public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHostedService<TimedHostedService>();
}

在控制台启动该项目,期间用 ctrl+C 结束应用.

其实官方帮我们封装了一个类来简化上述代码:

  /// <summary>
/// Base class for implementing a long running <see cref="T:Microsoft.Extensions.Hosting.IHostedService" />.
/// </summary>
public abstract class BackgroundService : IHostedService, IDisposable

因此上述代码可以修改成:

    public class MyBackGroundTask : BackgroundService
{
private readonly ILogger _logger; private Timer _timer; public MyBackGroundTask(ILogger<MyBackGroundTask> logger)
{
_logger = logger;
} protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($" MyBackGroundTask is starting. {DateTime.Now}");
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation($" MyBackGroundTask is working. {DateTime.Now}");
await Task.Delay(, stoppingToken);
}
_logger.LogInformation($" MyBackGroundTask is stopping. {DateTime.Now}");
}
}

但是,我发现

_logger.LogInformation($" MyBackGroundTask is stopping. {DateTime.Now}");

这句代码始终不执行.不知道是哪里没搞对.希望大神能帮个忙..

示例二:在后台任务中使用有作用域的服务

要使用有作用域的服务,需要先创建一个作用域.默认情况下,不会为托管服务创建作用域.

    public interface IScopedProcessingService
{
void DoWork();
} public class ScopedProcessingService : IScopedProcessingService
{
private readonly ILogger _logger;
public ScopedProcessingService(ILogger<ScopedProcessingService> logger)
{
_logger = logger;
}
public void DoWork()
{
_logger.LogInformation($"Scoped Processing Service is working. {DateTime.Now}");
}
}
    public class ConsumeScopedServiceHostedService : IHostedService
{ private readonly ILogger _logger; public IServiceProvider Services { get; } public ConsumeScopedServiceHostedService(IServiceProvider services, ILogger<ConsumeScopedServiceHostedService> logger)
{
Services = services;
_logger = logger;
} public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Consume Scoped Service Hosted Service is starting. {DateTime.Now}");
DoWork();
return Task.CompletedTask;
} private void DoWork()
{
_logger.LogInformation($"Consume Scoped Service Hosted Service is working. {DateTime.Now}");
using (IServiceScope scope = Services.CreateScope())//创建一个作用域.
{
IScopedProcessingService scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();
scopedProcessingService.DoWork();
}
} public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Consume Scoped Service Hosted Service is stopping. {DateTime.Now}");
return Task.CompletedTask;
}
}

但是我真的没搞懂官方这个例子的作用.因为托管服务只会激活一次,有作用域又有什么价值呢?希望哪位大哥能解答一下.

下面的在摘自网络:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_11.html

经测试:

  1. 当IIS上部署的项目启动后,后台任务随之启动,任务执行相应的log正常输出。

  2. 手动回收对应的应用程序池,任务执行相应的log输出停止。

  3. 重新请求该网站,后台任务随之启动,任务执行相应的log重新开始输出。

所以不建议在这样的后台任务中做一些需要固定定时执行的业务处理类的操作,但对于缓存刷新类的操作还是可以的,因为当应用程序池回收后再次运行的时候,后台任务会随着启动。

ASP.NET Core 2.2 基础知识(九) 使用托管服务实现后台任务的更多相关文章

  1. ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述

    为了方便演示,以 .NET Core 控制台应用程序讲解. 我们新建一个控制台应用程序,安装 "Newtonsoft.Json" Nuget 包,然后右键点击该项目,选择" ...

  2. ASP.NET Core 2.2 基础知识(十二) 发送 HTTP 请求

    可以注册 IHttpClientFactory 并将其用于配置和创建应用中的 HttpClient 实例. 这能带来以下好处: 提供一个中心位置,用于命名和配置逻辑 HttpClient 实例. 例如 ...

  3. ASP.NET Core 2.2 基础知识(十六) SignalR 概述

    我一直觉得学习的最好方法就是先让程序能够正常运行,才去学习他的原理,剖析他的细节. 就好像这个图: 所以,我们先跟着官方文档,创建一个 SignalR 应用: https://docs.microso ...

  4. ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)

    要啥自行车,直接看手表 //返回基元类型 public string Get() { return "hello world"; } //返回复杂类型 public Person ...

  5. ASP.NET Core 2.2 基础知识(十三) WebAPI 概述

    我们先创建一个 WebAPI 项目,看看官方给的模板到底有哪些东西 官方给出的模板: [Route("api/[controller]")] [ApiController] pub ...

  6. ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  7. ASP.NET Core 2.2 基础知识(十) Web服务器 - Kestrel

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  8. ASP.NET Core 2.2 基础知识(八) 主机 (未完待续)

    主机负责应用程序启动和生存期管理.共有两个主机 API : 1.Web 主机 : 适用于托管 Web 应用,基于 IWebHostBuilder ; 2.通用主机 : 适用于托管非 Web 应用. 基 ...

  9. ASP.NET Core 2.2 基础知识(六) 配置(内含MySql+EF)

    先上一段代码,了解一下 .NET Core 配置数据的结构. 新建一个 控制台项目,添加一个文件 json.json ,文件内容如下: { "country": "cn& ...

随机推荐

  1. innodb log file与binlog的区别在哪里?

    Q: innodb log file与binlog的区别在哪里?有人说1.mysql的innodb引擎实际上是包装了inno base存储引擎.而innodb log file是由 inno base ...

  2. visio2013安装提示找不到Office.zh_cn\officeMUI.mis officemui.xml(转)

    windoes10 已经安装office2013后,想安装Visio2013,报错如题所示.解决方法我采用的是方法二:解压缩office2013的ISO包,解压缩Visio2013的ISO包,安装Vi ...

  3. 封装常用的Javascript跨浏览器方法

    var EventUntil={ // 跨浏览器的添加事件方法 addHandler:function(element,type,handler){ if(element.addEventListen ...

  4. [转]使用 LDAP 组或角色限制访问,包含部分单点登录SSO说明

    参考:http://www-01.ibm.com/support/knowledgecenter/api/content/SSEP7J_10.2.2/com.ibm.swg.ba.cognos.crn ...

  5. 【洛谷】P1648 看守 (数学)

    题目链接 直接暴力搞\(O(n^2)\)显然是布星滴. 试想,若是一维,最远距离就是最大值减最小值. 现在推广到二维,因为有绝对值的存在,所以有四种情况 \((x1+y1) - (x2+y2), (x ...

  6. 滑杆(JSlider)和进度指示条(JProgressBar) 的使用

    package first; import javax.swing.*; import javax.swing.border.TitledBorder; import java.awt.*; impo ...

  7. mongodb的数据库操作

    1.创建数据库 语法 MongoDB 创建数据库的语法格式如下: use DATABASE_NAME 如果数据库不存在,则创建数据库,否则切换到指定数据库. 1.创建数据库 > show dbs ...

  8. virtualbox网络相关

    前言 Baidu/google了n多次, 效果不佳. 网上说的都是比较老的virtualbox版本,有的是默认就bridge方式(2.2.0前), 有的不是bridge方式的,是通过工具uml-uti ...

  9. UVALIVE 2686 Stargates

    尼玛真深坑合时p[x] = y 就RE,p[y] = x 就AC . #include <map> #include <set> #include <list> # ...

  10. 让div垂直居中于浏览器窗口

    <style type="text/css">  div  {   position:absolute;   top:50%;   left:50%;   margin ...