如何使用取消令牌停止范围服务?
Posted
技术标签:
【中文标题】如何使用取消令牌停止范围服务?【英文标题】:How to stop scoped service using Cancellation Token? 【发布时间】:2021-05-13 22:03:52 【问题描述】:我正在寻找一种使用Cancellation Token
来阻止Scoped background service
的方法。我按照以下步骤操作:
ScopedAlertingService.cs
namespace BackgroundTasksSample.Services
internal interface IScopedAlertingService
Task DoWork(System.Threading.CancellationToken stoppingToken);
public class ScopedAlertingService : IScopedAlertingService
private int executionCount = 0;
private readonly ILogger _logger;
public ScopedAlertingService(ILogger<ScopedAlertingService> logger)
_logger = logger;
public async Task DoWork(System.Threading.CancellationToken stoppingToken)
while (!stoppingToken.IsCancellationRequested)
executionCount++;
_logger.LogInformation(
"Alert: Scoped Processing Service is working. Count: Count", executionCount);
ConsumedServiceHostedService.cs
namespace BackgroundTasksSample.Services
public class ConsumeScopedServiceHostedService : BackgroundService
private readonly ILogger<ConsumeScopedServiceHostedService> _logger;
public ConsumeScopedServiceHostedService(IServiceProvider services,
ILogger<ConsumeScopedServiceHostedService> logger)
Services = services;
_logger = logger;
public IServiceProvider Services get;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
CancellationTokenSource _stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
_stoppingCts.CancelAfter(30000);
_logger.LogInformation(
"Consume Scoped Service Hosted Service running.");
while (!stoppingToken.IsCancellationRequested)
await Task.Delay(10000, stoppingToken);
using (var scope = Services.CreateScope())
var scopedProcessingService =
scope.ServiceProvider
.GetRequiredService<IScopedAlertingService>();
await scopedProcessingService.DoWork(stoppingToken);
private async Task DoWork(CancellationToken stoppingToken)
_logger.LogInformation(
"Consume Scoped Service Hosted Service is working.");
using (var scope = Services.CreateScope())
var scopedProcessingService =
scope.ServiceProvider
.GetRequiredService<IScopedAlertingService>();
await scopedProcessingService.DoWork(stoppingToken);
public override async Task StopAsync(CancellationToken stoppingToken)
_logger.LogInformation(
"Consume Scoped Service Hosted Service is stopping.");
await Task.CompletedTask;
我正在使用 IServiceCollection
运行此服务
#region snippet2
services.AddHostedService<ConsumeScopedServiceHostedService>();
services.AddScoped<IScopedAlertingService, ScopedAlertingService>();
#endregion
我正在使用以下代码在 30 秒后停止服务:
CancellationTokenSource _stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
_stoppingCts.CancelAfter(30000);
但是调试器不会去ConsumeScopedServiceHostedService
的stopAsync
方法。我在这里做错了什么?谢谢
【问题讨论】:
你怎么证明没有停止?我的意思是您的日志中将包含数百万个事件executionCount++; _logger.LogInformation("
您只是在尽可能快地在循环中破坏 cpu 核心。我认为你需要重新考虑你的测试
linked token sources 的目的与您所做的相反。链接 CTS 旨在监听链接令牌中的取消,而不是宣传取消。
@00110001 因为我放了调试器,还尝试添加console.writeline
。测试用例工作正常。我正在寻找一种在 30 秒后停止服务的方法,我可以看到计数器超过 100 秒。所以,当我检查我的控制台时。它不在那里。 (在上面的代码中也添加了console.writeline)
@Nick 啊!你能告诉我应该如何停止服务或如何在这里传递停止的令牌吗?
您正在创建链接令牌源而不使用其令牌?本质上你只是忽略它
【参考方案1】:
您可以将IHostedService
注入为Singleton
然后您可以在后台服务上调用停止方法。
更新: 在托管服务中,stopasync 仅在应用程序关闭时调用,但在您的代码中您可以使用它并且它可以工作:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
CancellationTokenSource _stoppingCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
_stoppingCts.CancelAfter(30000);
_logger.LogInformation(
"Consume Scoped Service Hosted Service running.");
while (!_stoppingCts.Token.IsCancellationRequested)
await Task.Delay(10000, _stoppingCts.Token);
using (var scope = Services.CreateScope())
var scopedProcessingService =
scope.ServiceProvider
.GetRequiredService<IScopedAlertingService>();
await scopedProcessingService.DoWork(_stoppingCts.Token);
【讨论】:
感谢您的回答赛义德。这是哪个控制器?我需要创建一个新的控制器还是你在谈论ConsumeScopedServiceHostedService
@Payal_Thakur 控制器或任何您想通过CancellationToken
的地方,如果您没有任何控制器(如果您的项目不是 Web 应用程序)。您可以执行选项 2。
我使用了第二个选项并在启动时更新了配置文件,但结果是一样的。
` services.AddSingletonStopAsync
方法。这不寻常吗?以上是关于如何使用取消令牌停止范围服务?的主要内容,如果未能解决你的问题,请参考以下文章
在 useEffect 挂钩中使用 axios 取消令牌时如何修复失败的测试