在大部分程序中一般都会需要用到后台任务, 比如定时更新缓存或更新某些状态。(ASP.NET Core 系列目录

一、应用场景

  以调用微信公众号的Api为例, 经常会用到access_token,官方文档这样描述:“是公众号的全局唯一接口调用凭据,有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效,建议公众号开发者使用中控服务器统一获取和刷新Access_token,其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务。”

  在这个场景中我们可以创建一个后台运行的服务,按照access_token的有效期定时执行去请求获取新的access_token并存储,其他所有需要用到这个access_token的都到这个共有的access_token。

二、实现方式(一)

  ASP.NET Core 在2.0的时候就提供了一个名为IHostedService的接口,我们要做的只有两件事:

    1. 实现它。

    2. 将这个接口实现注册到依赖注入服务中。

  A. 实现IHostedService的接口

首先看一下这个IHostedService:

    public interface IHostedService
{
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
}

通过名字就可以看出来,一个是这个服务启动的时候做的操作,另一个则是停止的时候。

新建一个类 TokenRefreshService  实现 IHostedService ,如下面代码所示:

     internal class TokenRefreshService : IHostedService, IDisposable
{
private readonly ILogger _logger;
private Timer _timer; public TokenRefreshService(ILogger<TokenRefreshService> logger)
{
_logger = logger;
} public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Service starting");
_timer = new Timer(Refresh, null, TimeSpan.Zero,TimeSpan.FromSeconds());
return Task.CompletedTask;
} private void Refresh(object state)
{
_logger.LogInformation(DateTime.Now.ToLongTimeString() + ": Refresh Token!"); //在此写需要执行的任务 } public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Service stopping");
_timer?.Change(Timeout.Infinite, );
return Task.CompletedTask;
} public void Dispose()
{
_timer?.Dispose();
}
}

既然是定时刷新任务,那么就用了一个timer, 当服务启动的时候启动它,由它定时执行Refresh方法来获取新的Token。

这里为了方便测试写了5秒执行一次, 实际应用还是读取配置文件比较好, 结果如下:

BackService.TokenRefreshService:Information: ::: Refresh Token!
BackService.TokenRefreshService:Information: ::: Refresh Token!
BackService.TokenRefreshService:Information: ::: Refresh Token!
BackService.TokenRefreshService:Information: ::: Refresh Token!
BackService.TokenRefreshService:Information: ::: Refresh Token!

B. 在依赖注入中注册这个服务。

在Startup的ConfigureServices中注册这个服务,如下代码所示:

services.AddSingleton<IHostedService, TokenRefreshService>();

三、实现方式(二)

在 ASP.NET Core 2.1中, 提供了一个名为 BackgroundService  的类,它在 Microsoft.Extensions.Hosting 命名空间中,查看一下它的源码:

 using System;
using System.Threading;
using System.Threading.Tasks; namespace Microsoft.Extensions.Hosting
{
/// <summary>
/// Base class for implementing a long running <see cref="IHostedService"/>.
/// </summary>
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource(); /// <summary>
/// This method is called when the <see cref="IHostedService"/> starts. The implementation should return a task that represents
/// the lifetime of the long running operation(s) being performed.
/// </summary>
/// <param name="stoppingToken">Triggered when <see cref="IHostedService.StopAsync(CancellationToken)"/> is called.</param>
/// <returns>A <see cref="Task"/> that represents the long running operations.</returns>
protected abstract Task ExecuteAsync(CancellationToken stoppingToken); /// <summary>
/// Triggered when the application host is ready to start the service.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
public virtual Task StartAsync(CancellationToken cancellationToken)
{
// Store the task we're executing
_executingTask = ExecuteAsync(_stoppingCts.Token); // If the task is completed then return it, this will bubble cancellation and failure to the caller
if (_executingTask.IsCompleted)
{
return _executingTask;
} // Otherwise it's running
return Task.CompletedTask;
} /// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// </summary>
/// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
// Stop called without start
if (_executingTask == null)
{
return;
} try
{
// Signal cancellation to the executing method
_stoppingCts.Cancel();
}
finally
{
// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, cancellationToken));
}
} public virtual void Dispose()
{
_stoppingCts.Cancel();
}
}
}

可以看出它一样是继承自 IHostedService, IDisposable , 它相当于是帮我们写好了一些“通用”的逻辑, 而我们只需要继承并实现它的 ExecuteAsync 即可。

也就是说,我们只需在这个方法内写下这个服务需要做的事,这样上面的刷新Token的Service就可以改写成这样:

     internal class TokenRefreshService : BackgroundService
{
private readonly ILogger _logger; public TokenRefreshService(ILogger<TokenRefresh2Service> logger)
{
_logger = logger;
} protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Service starting"); while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation(DateTime.Now.ToLongTimeString() + ": Refresh Token!");//在此写需要执行的任务
await Task.Delay(, stoppingToken);
} _logger.LogInformation("Service stopping");
}
}

是不是简单了不少。(同样这里为了方便测试写了5秒执行一次)

四. 注意事项

感谢@ 咿呀咿呀哟在评论中的提醒,当项目部署在IIS上的时候, 当应用程序池回收的时候,这样的后台任务也会停止执行。

经测试:

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

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

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

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

github地址

ASP.NET Core 2.1 : 十一. 如何在后台运行一个任务的更多相关文章

  1. [ASP.NET Core 3框架揭秘] 依赖注入[4]:一个Mini版的依赖注入框架

    在前面的章节中,我们从纯理论的角度对依赖注入进行了深入论述,我们接下来会对.NET Core依赖注入框架进行单独介绍.为了让读者朋友能够更好地理解.NET Core依赖注入框架的设计与实现,我们按照类 ...

  2. 如果你想深刻理解ASP.NET Core请求处理管道,可以试着写一个自定义的Server

    我们在上面对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了详细介绍(<聊聊ASP.NET Core默认提供的这个跨平台的服务器——KestrelServer& ...

  3. ASP.NET Core MVC应用程序中的后台工作任务

    在应用程序的内存中缓存常见数据(如查找)可以显着提高您的MVC Web应用程序性能和响应时间.当然,这些数据必须定期刷新. 当然你可以使用任何方法来更新数据,例如Redis中就提供了设定缓存对象的生命 ...

  4. 解决ASP.NET Core部署到IIS,更新项目"另一个程序正在使用此文件,进程无法访问"

    问题:部署到IIS上的ASP.NET Core项目,在更新的时候会进程占用的错误 初步解决方案: 1,关闭应用程序池 2,关闭网站 3,更新项目 缺点:网站没法访问,部署项目停的时间过长 查询官方文档 ...

  5. ASP.NET Core系列(二):创建第一个.Net Core 项目

    前面讲过 .NET Core简介及开发环境安装,本章会讲一讲ASP.NET Core 2.0的项目结构,查看完整的ASP.NET Core系列文章:https://www.cnblogs.com/zh ...

  6. 基于ASP.Net Core开发的一套通用后台框架

    基于ASP.Net Core开发一套通用后台框架 写在前面 这是本人在学习的过程中搭建学习的框架,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 知其然,知其所以然,并非重 ...

  7. 【低码】asp.net core 实体类可生产 CRUD 后台管理界面

    前言介绍 喜欢小规模团队的"单打独斗",有的时候即使在大公司,也经常做着3-5个人团队的小项目,相信很多人有类似的经历. 本文介绍如何将项目中已存在的[实体类],直接生产出 CRUD 后台管理界面. ...

  8. ASP.NET Core SignalR :学习消息通讯,实现一个消息通知

    什么是 SignalR 目前我用业余时间正在做一个博客系统,其中有个功能就是评论通知,就是假如A用户评论B用户的时候,如果B用户首页处于打开状态,那么就会提示B用户有未读消息.暂时用SignalR来实 ...

  9. ASP.NET CORE dotnet run 命令使用debug方式运行

    由于我的开发环境比较复杂,每次调试一套项目都要启动好几个VS,比较繁琐,今天决定换一种方式调试,对于不该改动的代码的附加项目直接使用dotnet run命令以debug的运行方式运行, 一开始无法运行 ...

随机推荐

  1. ionic4 开发企业微信应用0

    作为一个后台开发人员,几年前参与过Ionic1开发过一微信公众号的经历,所以这次开发企业微信应用,就使用了ionic,正好ionic4 rc版本发布,虽然不是正式版,作为本项目的项目经理,还是决定使用 ...

  2. ipset和iptables配合来自动封闭和解封有问题的IP

    iptables封掉少量ip处理是没什么问题的,但是当有大量ip攻击的时候性能就跟不上了,iptables是O(N)的性能.而ipset就像一个集合,把需要封闭的ip地址放入这个集合中,ipset 是 ...

  3. Linux神奇命令之---tar

    在生产中会常常用到压缩,解压缩,打包,解包等,这时候tar这个万能的小老弟就是是必不可少的了.linux中最流行的tar是麻雀虽小,五脏俱全,功能强大. tar命令可以为linux的文件和目录创建档案 ...

  4. BUAA-OO-第二单元总结

    OO第二单元总结 一.第五次作业 1.1 设计策略与架构 第五次作业要求的是完成设计支持一架傻瓜电梯的电梯系统.考虑到需要数据结构存放所有的请求,因此构建了FloorRequests类用来存放所有的请 ...

  5. Katalon Studio之swagger中的API导入

    约束条件: swagger中一定要在注解@ApiOperation中设置nickname的唯一值,例如: @ApiOperation(value="新增用户",notes=&quo ...

  6. 使用Bandwagon服务器ftp解决git clone速度慢的问题

    写在前面 git clone速度往往很慢,我们可以先在身处美国的服务器上git clone,然后把文件用ftp传回来即可. 开始 我们以opencv为例 git clone https://githu ...

  7. xgboost 多gpu支持 编译

    xgboost 多gpu支持 编译 Ubuntu 18.04.2Linux 4.15.0-46-genericgcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 cuda ...

  8. 让 ComboBox 的每个栏目显示不同颜色

    在一般的应用程式中,使用 ComboBox 提供下拉选单的功能,让使用者选择不同项目,一般而言, ComboBox 的项目没有什么特别的,但在特定的应用程式中,有时候会希望每个项目有一些效果呈现,例如 ...

  9. go 使用 c接口

    在使用go语言时, 有时为了方便可以直接调用c语言的接口与库, 不需要重复编写. 那就来说说在go语言里面如何调用c的接口 首先编写好c语言的源文件与头文件,这里举一个简单的例子,实现一个字符串大小写 ...

  10. MongoDB 分片键的选择与案例

    MongoDB版本:3.6 一.分片键类别 1.升序片键 升序片键例如:日期时间字段.自增字段. 2.随机分发片键 随机分发片键例如:用户名.邮件名.UUID.MD5值或者是其它的一些没有规律的值的列 ...