Фоновые службы запускаются при запуске приложения, а затем синхронизировать его с вами.
Вы можете реализовать службу backhround, используя класс BackgroundService
из пространства имен Microsoft.Extensions.Hosting
(Microsoft.Extensions.Hosting.Abstractions
сборка):
Сначала объявите интерфейс вашего сервиса (в данном случае он пустой, не красивый, но чистый):
public interface IMyService : IHostedService
{
}
Затем объявите свой сервис. Следующий фрагмент кода объявляет службу, которая запускается при запуске в течение 5 секунд, а затем выполняет задачу каждые 2 с половиной минуты:
internal sealed class MyService : BackgroundService, IMyService
{
private const int InitialDelay = 5 * 1000; //5 seconds;
private const int Delay = (5 * 60 * 1000) / 2; // 2.5 minutes
private readonly ILogger<MyService> m_Logger;
public MyService(ILogger<MyService> logger, IServiceProvider serviceProvider)
{
if (logger == null)
throw new ArgumentNullException(nameof(logger));
if (serviceProvider == null)
throw new ArgumentNullException(nameof(serviceProvider));
this.m_Logger = logger;
this.m_ServiceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
m_Logger.LogDebug($"MyService is starting.");
stoppingToken.Register(() => m_Logger.LogDebug($"MyService background task is stopping because cancelled."));
if (!stoppingToken.IsCancellationRequested)
{
m_Logger.LogDebug($"MyService is waiting to be scheduled.");
await Task.Delay(InitialDelay, stoppingToken);
}
m_Logger.LogDebug($"MyService is working.");
while (!stoppingToken.IsCancellationRequested)
{
await DoSomethingAsync();
await Task.Delay(Delay);
}
m_Logger.LogDebug($"MyService background task is stopping.");
}
catch (Exception ex)
{
m_Logger.LogDebug("MyService encountered a fatal error while w task is stopping: {Exception}.", ex.ToString());
}
}
private async Task DoSomrthingAsync()
{
// do something here
await Task.Delay(1000);
}
}
Как видите, вы должны поддерживать фоновую службу "живой". Наконец, вы должны зарегистрировать его в вашем Startup.cs
в конце вашего ConfigureServices
метода:
services.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, MyService>();
Этого достаточно для запуска службы. имейте в виду, что ваше приложение может быть действительно запущено позднее, если оно размещено в IIS: ваше приложение (пере) запускается каждый раз, когда ваша сборка перерабатывается. Вместо этого, используя Kestrel, вы получаете одно приложение, которое не будет переработано.
Для тех, кто использует .Net Core 2.1 или ниже, класс Background недоступен, но вы можете получить определение из github (я публикую то, что я использовал в прошлом, так как репозиторий github можно перемещать):
//borrowed from .NET Core 2.1 (we are currently targeting 2.0.3)
// Copyright (c) .NET Foundation. Licensed under the Apache License, Version 2.0.
/// <summary>
/// Base class for implementing a long running <see cref="IHostedService"/>.
/// </summary>
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts =
new CancellationTokenSource();
protected abstract Task ExecuteAsync(CancellationToken cancellationToken);
public virtual Task StartAsync(CancellationToken cancellationToken)
{
// Store the task we're executing
_executingTask = ExecuteAsync(_stoppingCts.Token);
// If the task is completed then return it,
// this will bubble cancellation and failure to the caller
if (_executingTask.IsCompleted)
{
return _executingTask;
}
// Otherwise it's running
return Task.CompletedTask;
}
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
// Stop called without start
if (_executingTask == null)
{
return;
}
try
{
// Signal cancellation to the executing method
_stoppingCts.Cancel();
}
finally
{
// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,
cancellationToken));
}
}
public virtual void Dispose()
{
_stoppingCts.Cancel();
}
}