【发布时间】: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 啊!你能告诉我应该如何停止服务或如何在这里传递停止的令牌吗?
-
您正在创建链接令牌源而不使用其令牌?本质上你只是忽略它
标签: c# visual-studio asp.net-core asp.net-core-2.0