如何从控制器重新启动BackgroundService

3

我创建了WcBackgroundService(继承自BackgroundService),并将其注入到OrdersController中。当前端API发送重启端点的请求时,我将从我的工作程序中执行Restart方法。

如上所述,当前解决方案不仅重新启动服务,而且还创建了我的后台服务的新实例并启动它。

以下是我的代码

WcBackgroundService

public async Task Restart()
{
    await StopAsync(new CancellationToken());
    await StartAsync(new CancellationToken());
}

protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
     cancellationToken.Register(() =>
     {
         _logger.Debug($"Service {_serviceType} is stopping.");
     });

     while (!cancellationToken.IsCancellationRequested)
     {
         await DoWork();
     }
}

在启动文件中的 ConfigureServices 方法:

..
services.AddSingleton<IWcBackgroundService, WcBackgroundService>();
..

启动时配置:

var wcBackgroundService = app.ApplicationServices.GetService<IWcBackgroundService>();
wcBackgroundService.StartAsync(new CancellationToken()).Wait();

我看到了这个任务,并像这样注册我的BackgroundService:services.AddSingleton<IHostedService, MyBackgroundService>();(IWcBackgroundService继承自IHostedService) - Mariusz D.
1个回答

3
您必须使用在开头传递的同一令牌进行取消,只有这样才能取消后台任务。
您应该在任务中实现取消操作,通过正确传递和存储在某个地方的令牌进行取消。例如,实现一个任务管理服务,将其注册为DI容器中的单例(如果通过属性公开,则还可以从wcBackGroundService中获取令牌),然后实现一个控制器端点,比如“RestartBackgroundTask”,从单例服务获取令牌或tokenSource并取消它,然后再次调用start方法。您可以将task.Start移动到单独的函数中,以便在不重复代码的情况下调用相同的逻辑。 了解cancellationTokenSource

1
谢谢,它正在工作 :) 我创建了一个 CancellationTokenSource,在 Restart 方法中被取消。取消后,我必须等待当前作业完成,然后使用新的 CancellationTokenSource 开始。 - Mariusz D.
在使用异步等待模式时,请注意一点。不要使用Task.Wait()或xy.Result进行等待。始终使用xyTask.GetAwaiter().GetResult()或仅使用await。 - Kristóf Tóth
在类似的工作时,我遇到了一个问题,因为我将相同的取消令牌传递给了停止和开始方法。我的疏忽在于后台服务中的停止方法会调用.Cancel()取消令牌,因此如果您想重新启动它,需要创建一个新的取消令牌。 - Newteq Developer
@MariuszD,请您能否发布一个对您有效的样例代码?我也遇到了同样的问题。提前致谢。 - Hitesh Patel

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