Skip to main content

实现自己的IHostedService

分类:  .Net技术 标签:  #基础 #.Net Host #.Net 发布于: 2023-06-15 15:44:03

我们前面使用.NetWorker模板实现.Net Host的服务模型的时候,都使用了BackgroundService这个抽象类,如果想对于自己的后端应用有更多的定制,可以从接口IHostedService直接继承,然后实现更多的细节,我们这个实例直接实现接口IHostedService以及接口IAsyncDisposable, 同时向.Net Host模型注册服务都是使用的相同的扩展方法AddHostedService<T>()方法。

我们这一节实现使用System.Threading.Timer来实现一个定时的任务。

创建项目

使用.Net Cli来创建项目:

dotnet new worker -o CustomHostedService
cd CustomHostedService
code .

使用了Vs Code打开该目录之后,开始进行编辑。

实现IHostedService方法

使用VS CodeWorker.cs重命名为:TimeHostedService.cs, 并使用如下的内容重新定义该类。

namespace CustomHostedService;

public sealed class TimerHostedService : IHostedService, IAsyncDisposable
{
    private readonly Task _completedTask = Task.CompletedTask;
    private readonly ILogger<TimerHostedService> _logger;
    private int _executionCount = 0;
    private Timer? _timer;

    public TimerHostedService(ILogger<TimerHostedService> logger) => _logger = logger;

    public Task StartAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("{Service} is running.", nameof(TimerHostedService));
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return _completedTask;
    }

    private void DoWork(object? state)
    {
        int count = Interlocked.Increment(ref _executionCount);

        _logger.LogInformation(
            "{Service} is working, execution count: {Count:#,0}",
            nameof(TimerHostedService),
            count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation(
            "{Service} is stopping.", nameof(TimerHostedService));

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

        return _completedTask;
    }

    public async ValueTask DisposeAsync()
    {
        if (_timer is IAsyncDisposable timer)
        {
            await timer.DisposeAsync();
        }

        _timer = null;
    }
}

更改Program.cs

由于我们已经更改了Worker.cs的定义为TimerHostedService.cs, 因此我们也需要在Program.cs里进行更改:

using CustomHostedService;

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<TimerHostedService>();
    })
    .Build();

await host.RunAsync();

运行查看效果

在项目的根目录下运行dotnet run, 然后查看结果:

D:\MyProjects\DotNetLearning\CustomHostedService>dotnet run
正在生成...
info: CustomHostedService.TimerHostedService[0]
      TimerHostedService is running.
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\MyProjects\DotNetLearning\CustomHostedService
info: CustomHostedService.TimerHostedService[0]
      TimerHostedService is working, execution count: 1
info: CustomHostedService.TimerHostedService[0]
      TimerHostedService is working, execution count: 2
info: CustomHostedService.TimerHostedService[0]
      TimerHostedService is working, execution count: 3
info: CustomHostedService.TimerHostedService[0]
      TimerHostedService is working, execution count: 4
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: CustomHostedService.TimerHostedService[0]
      TimerHostedService is stopping.