在 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. [Leetcode] Multiply strings 字符串对应数字相乘

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...

  2. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

  3. Visaul Studio 常用快捷键动画演示

    从本篇文章开始,我将会陆续介绍提高 VS 开发效率的文章,欢迎大家补充~ 在进行代码开发的时候,我们往往会频繁的使用键盘.鼠标进行协作,但是切换使用两种工具会影响到我们的开发速度,如果所有的操作都可以 ...

  4. Java中Class<T>与Class<?>的区别

    E - Element (在集合中使用,因为集合中存放的是元素) T - Type(Java 类) K - Key(键) V - Value(值) N - Number(数值类型) ? - 表示不确定 ...

  5. powershell for rename server name

    Rename server name if server has not yet joined AD $Hostname = "newname" $username = " ...

  6. ubuntu安装GraphicsMagick

    一. sudo apt-get install graphicsmagick 二. http://www.cnblogs.com/cocowool/archive/2010/08/16/1800954 ...

  7. MyBatis对象关联关系----多对多的保存与查询

    模拟情景: 对象:学生,课程 关系:一个学生可选多个课程,一门课程可被多个学生选择 一.保存 1.创建数据库表,student,course,student_course,其中student_cour ...

  8. 如何让 linux unzip 命令 不输出结果

    unzip xx.zip > /dev/null 2>&1 unzip xx.zip > /dev/null前半部分是将标准输出重定向到空设备, 后面的2>&1 ...

  9. [BZOJ1982][POJ1740][Spoj 2021]Moving Pebbles|解题报告

    这道题的题意BZ和POJ上的都不大清楚... 大概就是给出n堆石子,以及初始每堆石子的个数 两个玩家交替操作,每个操作可以任意在一堆中取任意多的石子 然后再从这堆里拿若干个石子放到某个当前还存在的堆里 ...

  10. 160多条Windows 7 “运行”命令

    160多条Windows 7 “运行”命令: 删除或更改应用程序 = control appwiz.cpl 添加设备 = devicepairingwizard  蓝牙文件传输 = fsquirt  ...