如何在ASP.NET Core中手动重启BackgroundService

4
我创建了BackgroundService:
public class CustomService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        //...
    }
}

我添加到了这个项目中:

public class Startup
{
    //...

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHostedService<CustomService>();

        //...
    }

    //...
}

我该如何从另一个类中找到CustomService?
如何重新启动它?


请查看以下两个链接,看它们是否能对您有帮助:这个这个 - user1672994
这个回答解决了你的问题吗?如何从控制器重新启动BackgroundService - Nemanja Todorovic
2个回答

4
创建一个专门用于调用 StartAsync 的接口:
public interface ICustomServiceStarter
{
    Task StartAsync(CancellationToken token = default);
}

public class CustomService : BackgroundService, ICustomServiceStarter
{
    //...
    Task ICustomServiceStarter.StartAsync(CancellationToken token = default) => base.StartAsync(token);
    //...
}

将接口注册为单例:

public class Startup
{
    //...
    public void ConfigureServices(IServiceCollection services)
    {
        //...
        services.AddSingleton<ICustomServiceStarter, CustomService>();
    }
    //...
}

在需要时注入 ICustomServiceStarter

public class MyServiceControllerr : Controller
{
    ICustomServiceStarter _starter;

    public MyServiceController(ICustomServiceStarter starter)
    {
        _starter = starter;
    }

    [HttpPost]
    public async Task<IActionResult> Start()
    {
        await _starter.StartAsync();

        return Ok();
    }
}

3

当涉及到控制器的操作时,对于长时间运行的任务,使用"await BackgroundService.StartAsync"是错误的方式。

例如,主要问题可能取决于代理设置而导致请求超时。

以下是如何使您的BackgroundService可重启的示例。

BackgroundService实现:

public class MyBackgroundService: BackgroundService
{
  private volatile bool _isFinished = false;
  private SemaphoreSlim _semaphore = new SemaphoreSlim(0,1);

  protected override async Task ExecuteAsync(CancellationToken stoppingToken)
  {
    _isFinished = false;
     // DoSomeWork
    _isFinished = true;
    await WaitToRestartTask(stoppingToken);
  }

  private async Task WaitToRestartTask(CancellationToken stoppingToken)
  {
     // wait until _semaphore.Release()
     await _semaphore.WaitAsync(stoppingToken);
     // run again
     await base.StartAsync(stoppingToken);
  }

  public void RestartTask()
  {
     if (!_isFinished)
          throw new InvalidOperationException("Background service is still working");

     // enter from _semaphore.WaitAsync
     _semaphore.Release();
  }  
}

控制器的操作(例如):

public async Task<IActionResult> Restart()
{
    var myBackgroundService= _serviceProvider.GetServices<IHostedService>()
                .OfType<MyBackgroundService>()
                .First();

    try
    {
       myBackgroundService.RestartTask();
       return Ok($"MyBackgroundService was restarted");
    }
    catch (InvalidOperationException exception)
    {
       return BadRequest(exception.Message);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接