5

NetCore如何使用托管服务执行后台任务

 3 years ago
source link: https://my.oschina.net/u/3081398/blog/5037113
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者博客|文章首发

我们经常要使用NetCore控制台或者AspNetCore来定义一些通用的后台服务。如果自行编码的话,对后台服务的理解应该体现在启动一个线程,使用while循环执行任务,每次时间间隔N秒,这是最简单的一种实现方式。

既然NetCore现在的稳定版本都已经是3.1了,难道官方没有考虑到这种最基本的使用场景吗。当然不会,下面我们就本着参考官方文档的角度解析一下后台服务在Core控制台中的使用。

初始化准备

首先我们创建一个控制台项目,下载基础包

nuget install Microsoft.Extensions.Hosting

初始化Program.cs文件

public static class Program
{
    static async void Main(string[] args)
    {
        var builder = new HostBuilder().ConfigureServices((context, service) =>
        {

        });

        await builder.RunConsoleAsync();
    }
}

一般后台服务

注入后台服务非常简单,调用service.AddHostedService方法将自定义的服务进行注入。

service.AddHostedService<CustomerJob/Service>();

自定义的后台服务类需要满足定义的接口,才可以被正常使用,下面我引用一个官方的案例进行说明

定时后台任务使用 [System.Threading.Timer]类。 计时器触发任务的 DoWork 方法。 在 StopAsync 上禁用计时器,并在 Dispose 上处置服务容器时处置计时器:

继承IHostedService接口,实现StartAsyncStopAsync方法即可将服务正常注入后台任务中。

IDisposable的作用主要是在进程关闭时释放定时器资源

public class TimedHostedService : IHostedService, IDisposable
{
    private int executionCount = 0;
    private readonly ILogger<TimedHostedService> _logger;
    private Timer _timer;

    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
    }

    public Task StartAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        var count = Interlocked.Increment(ref executionCount);

        _logger.LogInformation(
            "Timed Hosted Service is working. Count: {Count}", count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

将上文中的内容进行一个整合,得到的效果是

public static class Program
{
    static async void Main(string[] args)
    {
        var builder = new HostBuilder().ConfigureServices((context, service) =>
        {
        	service.AddHostedService<TimedHostedService>();
        });

        await builder.RunConsoleAsync();
    }
}

Ctrl+F5即可查看执行效果

以上说明的是后台任务在Core控制台中的应用,那么在AspNetCore【Web项目】中是怎么使用的呢。当然都是一样的,只是注入的地方发生了小小的改变,在AspNetCore中注入通常发生在StartUp.cs中的方法ConfigureServices。使用方法和控制台一致。

public void ConfigureServices(IServiceCollection services)
{
	service.AddHostedService<TimedHostedService>();
}

带作用域的服务

适用于Web项目中涉及数据库等外连接操作的场景,例如

每一次web请求对应一个数据库上下文[DbContext],这个时候就要用要带作用域的服务。

带作用域的服务使用也非常简单,可以参考官方文档,这里我就不做其他介绍

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio

https://blog.csdn.net/weixin_34174105/article/details/86015664

Redis工具收费后新的开源已出现

GitHub上Star最高的工程师技能图谱

中国程序员最容易发错的单词

推荐!!! Markdown图标索引网站

本文到此结束,希望对你有帮助 😃

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

更多精彩技术文章汇总在我的 公众号【程序员工具集】,持续更新,欢迎关注订阅收藏。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK