net core-调用接口方式实现IHostedService的停止和启动

一 基本代码实现: 
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;

[Route("home")]
[AllowAnonymous]
public class HomeController : ControllerBase {
 private readonly IEnumerable<IHostedService> _hostedServices;
 private readonly RecureHostedService _recureHostedService;

 public HomeController(IEnumerable<IHostedService> hostedServices)
 {
     //_recureHostedService = hostedService;// as RecureHostedService;
     // var hosteds = services.BuildServiceProvider().GetServices<IHostedService>();
     _hostedServices = hostedServices;
     _recureHostedService = _hostedServices.First(t => t is RecureHostedService) as RecureHostedService;
 }
 
[Route("About")]
 public IActionResult About()
 {
     //ViewData["Message"] = "Your application description page.";
     _recureHostedService.StopAsync(new System.Threading.CancellationToken());
     return Ok("Hello from Recure.");
 }
 [Route("Contact")]
 public IActionResult Contact()
 {
     // ViewData["Message"] = "Your contact page.";
     _recureHostedService.StartAsync(new System.Threading.CancellationToken());
     return Ok("Your contact page.");
 } }

public class RecureHostedService : IHostedService, IDisposable
 {
private readonly ILogger _log;
private Timer _timer;
public RecureHostedService(ILogger<RecureHostedService> log)
{
    _log = log;
}

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

public Task StartAsync(CancellationToken cancellationToken)
{
    _log.LogInformation("RecureHostedService is Starting");
    _timer = new Timer(DoWork,null,TimeSpan.Zero, TimeSpan.FromSeconds(5));
    return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
    _log.LogInformation("RecureHostedService is Stopping");
    _timer?.Change(Timeout.Infinite, 0);
    return Task.CompletedTask;
}
private void DoWork(object state)
{
    _log.LogInformation("Timed Background Service is working.");
}
}

在program.cs中:

builder.Services.AddSingleton<IHostedService, RecureHostedService>();
二 使用.Net6新定时器PeriodicTimer优化: 
1 新建backgroundSerices
public class MyHostedService : BackgroundService
{
    private readonly ILogger<MyHostedService> _logger;
    private PeriodicTimer _timer;
    public MyHostedService(ILogger<MyHostedService> logger)
    {
        _logger = logger;
    }

    private readonly TimeSpan timeSpan = TimeSpan.FromSeconds(30); // 1 second.
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _timer = new PeriodicTimer(timeSpan);
        try
        {
            while (!stoppingToken.IsCancellationRequested &&
            await _timer.WaitForNextTickAsync(stoppingToken))
            {
                _logger.LogInformation("Executing PeriodicBackgroundTask");
                System.Console.WriteLine("Executing PeriodicBackgroundTask");
            }
        }
        catch
        {
            _timer.Dispose();
        }

    }

    public override Task StartAsync(CancellationToken cancellationToken)
    {
        return base.StartAsync(cancellationToken);
    }

    public override Task StopAsync(CancellationToken cancellationToken)
    {
        _timer.Dispose();
        return base.StopAsync(cancellationToken);
    }
}

2 添加注入到Promgram.cs中

3 控制器

using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]/[action]")]
public class HostServiceContoller : ControllerBase
{
     private readonly MyHostedService _myHostedService;

    public HostServiceContoller(IEnumerable<IHostedService> hostedServices)
    {
        _myHostedService = hostedServices.First(t => t is MyHostedService) as MyHostedService;
    }

    [HttpGet]
    public async Task<IActionResult> StopMyService()
    {
        _myHostedService.StopAsync(new System.Threading.CancellationToken());
        return NoContent();
    }

    [HttpGet]
    public async Task<IActionResult> StartMyService()
    {
        _myHostedService.StartAsync(new System.Threading.CancellationToken());
        return NoContent();
    }
}

--

PeriodicTimer相比之前的Timer来说,有下面几个特点:

没有callback来绑定事件;
不会发生重入,只允许有一个消费者,不允许同一个PeriodicTimer在不同的地方同时WaitForNextTickAsync,不需要自己做排他锁来实现不能重入;
异步化。之前的timer的callback都是同步的,使用新timer可以使用异步方法,避免了编写Sync over Async代码;
Dispose之后,实例就无法使用,并且WaitForNextTickAsync始终返回false。
 



posted @ 2023-05-31 10:19  vba是最好的语言  阅读(245)  评论(0编辑  收藏  举报