在 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. CSS样式权重的级联cascade的概念

    我们知道,firefox在众多浏览器中是对css 2高度兼容的一款浏览器,那是我能够编写一个中型b2b网站的时候(并不能说是我遇到过的难题)在禅意花园中看到的一个案例,说的是某个菜单在css中定义了以 ...

  2. 解决echarts中X轴文字过长的问题。【转】

    axisLabel: { interval: , formatter:function(value) { debugger var ret = "";//拼接加\n返回的类目项 ; ...

  3. 用boost::lexical_cast进行数值转换

    在STL库中,我们可以通过stringstream来实现字符串和数字间的转换: int i = 0;    stringstream ss; ss << "123";  ...

  4. bzoj 4624 农场种植 fft

    4624: 农场种植 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 48  Solved: 31[Submit][Status][Discuss] D ...

  5. Java并发(9)- 从同步容器到并发容器

    引言 容器是Java基础类库中使用频率最高的一部分,Java集合包中提供了大量的容器类来帮组我们简化开发,我前面的文章中对Java集合包中的关键容器进行过一个系列的分析,但这些集合类都是非线程安全的, ...

  6. 51Nod 1256 求乘法逆元--扩展欧几里德

    #include<stdio.h> int exgcd(int a,int b,int &x,int &y) { ) { x=; y=; return a; } int r ...

  7. CentOS7 Tomcat 启动过程很慢,JVM上的随机数与熵池策略

    1. CentOS7 Tomcat 启动过程很慢 在centos启动官方的tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的: <co ...

  8. 在liberty中通过LTPA设置单点登录

    不要忘了下面的设置,参考: https://www-01.ibm.com/support/knowledgecenter/was_beta_liberty/com.ibm.websphere.wlp. ...

  9. 【poj3693-重复次数最多的连续重复子串】后缀数组

    题意:给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个). 例如ccabcabc,答案就是abcabc 一开始没想清楚,结果调了好久. 原理: 按照L划分,因为 ...

  10. Vue 还是 React 还是 Angular ?

    有空的时候还是把3个都熟悉一下.除了Angular学习起来笔记花时间外.React跟Vue没啥难度,学习用的时间不多. 如果你在Google工作:Angular如果你喜欢TypeScript:Angu ...