我目前有一個帶有 .NET Core SDK v5.0.403 的 ASP.NET Core 應用程式。
在這個應用程式中,我BackgroundService定義了幾個,其中之一如下:
public class DueDateNotificationService : BackgroundService
{
private readonly ILogger _logger;
private readonly IServiceScopeFactory _serviceProvider;
private readonly int _actionDueDateGenerationDelay;
private readonly int _startupDelayInSeconds;
protected static int instances = 0;
public DueDateNotificationService(ILogger<DueDateNotificationService> logger,
IServiceScopeFactory serviceProvider,
IConfiguration configuration)
{
_logger = logger;
_serviceProvider = serviceProvider;
_actionDueDateGenerationDelay = configuration["BackgroundServices:DueDateNotificationService:DueDateGenerationDelay"].ToInt(240);
_startupDelayInSeconds = Math.Max(configuration["BackgroundServices:DueDateNotificationService:StartupDelayInSeconds"].ToInt(), 60);
}
/// <summary>
/// Service execution
/// </summary>
/// <param name="stoppingToken"></param>
/// <returns></returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Adding basic data to the logging context
using (LogContext.PushProperty("AppName", "Api-DueDateNotificationService"))
{
_logger.LogInformation("DueDateNotificationService Hosted Service is starting.");
await Task.Delay(TimeSpan.FromSeconds(_startupDelayInSeconds), stoppingToken);
while (!stoppingToken.IsCancellationRequested)
{
try
{
using (var scope = _serviceProvider.CreateScope())
{
var service = scope.ServiceProvider.GetRequiredService<IMyService>();
_logger.LogInformation($"doing stuff");
service.DoStuff();
}
// waiting until we should check again
_logger.LogInformation($"Job finished at {DateTime.UtcNow}. Next job at {DateTime.UtcNow.AddMinutes(_actionDueDateGenerationDelay)}");
await Task.Delay(TimeSpan.FromMinutes(_actionDueDateGenerationDelay));
}
catch (TaskCanceledException)
{
_logger.LogWarning("The DueDateNotificationService Hosted Service was cancelled, likely because the site was shutdown (possibly due to inactivity or a force update)");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error occurred executing the automated DueDateNotificationService service.");
}
}
_logger.LogInformation("DueDateNotificationService Hosted Service is stopping.");
}
}
我的服務僅在一個地方添加到 DI,在 startup.cs 中:
EnableHostedService<DueDateNotificationService>(services, "BackgroundServices:DueDateNotificationService:Enabled");
隨著 EnabledHostedService 是:
private IServiceCollection EnableHostedService<T>(IServiceCollection services, string configurationKey) where T : class, IHostedService
{
// Background services to run
if (Configuration[configurationKey].Equals("true", StringComparison.OrdinalIgnoreCase))
{
return services.AddHostedService<T>();
}
return services;
}
這是我注冊 backgroundService 的唯一地方,除了默認提供的之外,應用程式中的任何地方都沒有 autofac 或自定義 DI。
我的問題是,每當我的應用程式托管在 azure 應用程式服務中時,所有后臺服務都會一次運行多次。
當我查看我的日志時,
DueDateNotificationService 托管服務正在啟動。
至少顯示了兩次,我的 while 回圈中的所有日志也是如此(我在此處洗掉以減輕帖子的負擔)。
但是當我在本地除錯它時,它應該只運行一次。
When I comment my registration line, it is not started at all (even on Azure).
From what could it come?
Thanks
UPDATE I've even tried with something like:
protected static int instances = 0;
....
Interlocked.Increment(ref instances);
if (instances > 1)
{
_logger.LogInformation("An instance of DueDateNotificationService is already started.");
}
else
{
MyWhileLoop();
}
It still starts / executes several times, and the following log:
An instance of DueDateNotificationService is already started.
never appears.
uj5u.com熱心網友回復:
天藍色應用服務
這幾乎可以肯定是由于您的應用程式運行了多個實體。
除了通過一些資料持久化/簽入資料庫之外,讓后臺服務只運行一次的最安全方法是什么?
外部“租賃”是最安全的方法。您可以使用 CosmosDb / Redis 作為后端自己構建一個,也可以使用內置方法,將 Web 應用程式中的后臺服務分解為 Azure WebJob 或 Azure 函式。這兩個服務都自動為計時器觸發的作業使用租約。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/422419.html
標籤:
上一篇:VisualStudio-ASP.NETCore-添加新類時的問題
下一篇:如何獲得過去5年的銷售額百分比
