在 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. BZOJ2257 [Jsoi2009]瓶子和燃料 【裴蜀定理】

    题目链接 BZOJ2257 题解 由裴蜀定理我们知道,若干的瓶子如此倾倒最小能凑出的是其\(gcd\) 现在我们需要求出\(n\)个瓶子中选出\(K\)个使\(gcd\)最大 每个数求出因数排序即可 ...

  2. [SDOI2016] 排列计数 (组合数学)

    [SDOI2016]排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰 ...

  3. [hdu 6069]素数筛+区间质因数分解

    给[L,R]区间的每一个数都质因数分解的复杂度可以达到(R-L)logR,真的涨姿势…… 另外,质因数分解有很重要的一点,就是只需要打sqrt(R)以内的素数表就够了……因为超过sqrt(R)的至多只 ...

  4. Ecplise添加XML自动提示

    这里以struts.xml为例 第一步: 首先找到 struts2的核心jar包,我这里是struts2-core-2.3.20.jar用压缩工具打开或者解压下来

  5. nginx+webpy+uswgi+jwplayer组合搭建流媒体服务器

    转载自:http://blog.csdn.net/cjsafty/article/details/7892392 目前,由于Flash的流行,网络上绝大多数的微视频网站都采用了Flv格式来播放视频. ...

  6. 程序员的那些问题---转载自veryCD

    展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告   走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过 ...

  7. webpack 配置学习笔记

    最简单的 webpack 配置 const path = require('path') module.exports = { entry: './app/index.js', output: { p ...

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

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

  9. 关于MyBatis的collection集合中只能取到一条数据的问题

    问题:在涉及多表查询的时候,使用collection元素来映射集合属性时,出现了只能查询到一条数据的情况,但用sql语句在数据库中查询会有多条记录. 解决:如果两表联查,主表和明细表的主键都是id的话 ...

  10. nginx解决超长请求串(413 request Entity too Large错误解决办法)

    <div class="hide-article-box text-center" style="display: block;"> <a c ...