Wie kann ein benutzerdefinierter gehosteter Dienst in ASP.NET Core 2.1 ordnungsgemäß registriert werden? Zum Beispiel habe ich einen benutzerdefinierten gehosteten Dienst, der von BackgroundService mit dem Namen MyHostedService
abgeleitet ist. Wie soll ich es registrieren?
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//...
services.AddSingleton<IHostedService, MyHostedService>();
}
oder
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//...
services.AddHostedService<MyHostedService>();
}
?
hier wir können den ersten Fall sehen, aber hier es gibt den zweiten Fall.
Sind diese Methoden gleich?
Sie sind ähnlich, aber nicht vollständig
AddHostedService
ist Teil von Microsoft.Extensions.Hosting.Abstractions
.
Es gehört Microsoft.Extensions.Hosting.Abstractions
in der Klasse ServiceCollectionHostedServiceExtensions
using Microsoft.Extensions.Hosting;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionHostedServiceExtensions
{
/// <summary>
/// Add an <see cref="IHostedService"/> registration for the given type.
/// </summary>
/// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>
/// <param name="services">The <see cref="IServiceCollection"/> to register with.</param>
/// <returns>The original <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services)
where THostedService : class, IHostedService
=> services.AddTransient<IHostedService, THostedService>();
}
}
Beachten Sie, dass der Gültigkeitsbereich Transient
und nicht Singleton
verwendet wird.
Intern fügt das Framework alle gehosteten Dienste einem anderen Dienst hinzu (HostedServiceExecutor
)
public HostedServiceExecutor(ILogger<HostedServiceExecutor> logger,
IEnumerable<IHostedService> services) //<<-- note services collection
{
_logger = logger;
_services = services;
}
beim Start ist das ein Singleton über den WebHost Constructor .
_applicationServiceCollection.AddSingleton<HostedServiceExecutor>();
Benutze AddHostedService
Ein gehosteter Dienst ist mehr als nur ein Einzeldienst. Die Laufzeit "weiß" davon, kann sie anweisen, durch Aufrufen von StartAsync
zu starten oder durch Aufrufen von StopAsync()
zu stoppen, wenn z. B. der Anwendungspool wiederverwendet wird. Die Laufzeit kann warten, bis der gehostete Dienst beendet ist, bevor die Webanwendung selbst beendet wird.
Wie in der Dokumentation erläutert kann ein Dienst mit Gültigkeitsbereich verwendet werden , indem ein Bereich innerhalb der Worker-Methode des gehosteten Dienstes erstellt wird. Gleiches gilt für flüchtige Dienste.
Dazu muss ein IServicesProvider oder eine IServiceScopeFactory in den Konstruktor des gehosteten Dienstes eingefügt und zum Erstellen des Bereichs verwendet werden.
Aus den Dokumenten entlehnt, kann die Konstruktor- und Arbeitermethode des Dienstes folgendermaßen aussehen:
public IServiceProvider Services { get; }
public ConsumeScopedServiceHostedService(IServiceProvider services,
ILogger<ConsumeScopedServiceHostedService> logger)
{
Services = services;
_logger = logger;
}
private void DoWork()
{
using (var scope = Services.CreateScope())
{
var scopedProcessingService =
scope.ServiceProvider
.GetRequiredService<IScopedProcessingService>();
scopedProcessingService.DoWork();
}
}
Diese verwandte Frage zeigt, wie ein vorübergehender DbContext in einem gehosteten Dienst verwendet wird:
public class MyHostedService : IHostedService
{
private readonly IServiceScopeFactory scopeFactory;
public MyHostedService(IServiceScopeFactory scopeFactory)
{
this.scopeFactory = scopeFactory;
}
public void DoWork()
{
using (var scope = scopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
…
}
}
…
}