Sicherstellen, dass Ihr IHostedService eine einzige Instanz ist
Einleitung
Dies ist ein dummer kleiner Artikel, weil ich war etwas verwirrt darüber, wie zu gewährleisten, dass meine IHostedService Ich dachte, es sei ein bisschen komplizierter als es tatsächlich war, also dachte ich, dass I'"d einen kleinen Artikel darüber schreiben sollte.." Nur für den Fall, dass jemand anderes über ihn verwirrt wurde.
In der vorheriger ArtikelWir haben behandelt, wie man einen Hintergrund-Dienst mit dem IHostedService Schnittstelle für das Senden von E-Mails Dieser Artikel wird abdecken, wie Sie sicherstellen, dass Ihre IHostedService ist eine einzelne Instanz.
Dies könnte für einige offensichtlich sein, ,, aber es ist nicht zu anderen ( und war nicht sofort zu mir !).
Warum ist dies ein Problem?
Nun, es ist ein Problem, da die meisten der Artikel aus diesen umfassen, wie man eine IHostedService aber sie decken nicht ab, wie man sicherstellt, dass der Dienst eine einzelne Instanz ist. Dies ist wichtig, da du mehrere Instanzen des gleichzeitig laufenden Dienstes möchtest.
Was meine ich mit ? Nun in ASP-.'NET die Art und Weise, einen IHostedService oder IHostedlifeCycleService zu registrieren?
services.AddHostedService(EmailSenderHostedService);
Was das tut, ist Anrufe in diesen Backend-Code.
public static IServiceCollection AddHostedService<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THostedService>(this IServiceCollection services)
where THostedService : class, IHostedService
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, THostedService>());
return services;
}
Was ist in Ordnung und Dandy, aber was, wenn Sie eine neue Nachricht direkt an diesen Dienst posten von sagen ein Controller Aktion: ?-
public class ContactController(EmailSenderHostedService sender,ILogger<BaseController> logger) ...
{
[HttpPost]
[Route("submit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Submit([Bind(Prefix = "")] ContactViewModel comment)
{
ViewBag.Title = "Contact";
//Only allow HTMX requests
if(!Request.IsHtmx())
{
return RedirectToAction("Index", "Contact");
}
if (!ModelState.IsValid)
{
return PartialView("_ContactForm", comment);
}
var commentHtml = commentService.ProcessComment(comment.Comment);
var contactModel = new ContactEmailModel()
{
SenderEmail = string.IsNullOrEmpty(comment.Email) ? "Anonymous" : comment.Email,
SenderName = string.IsNullOrEmpty(comment.Name) ? "Anonymous" : comment.Name,
Comment = commentHtml,
};
await sender.SendEmailAsync(contactModel);
return PartialView("_Response",
new ContactViewModel() { Email = comment.Email, Name = comment.Name, Comment = commentHtml });
return RedirectToAction("Index", "Home");
}
}
Entweder müssen Sie eine Schnittstelle, die selbst implementiert erstellen IHostedService dann rufen Sie in die Methode auf, dass oder müssen Sie sicherstellen, dass der Dienst eine einzige Instanz ist...... letzteres ist der einfachste Weg, um dies zu tun, hängt von Ihrem Szenario ab.. ..
IHostedService
Sie beachten hier, dass es den Service als ein registriert IHostedServiceDies hat mit dem Lebenszyklus-Management dieses Dienstes zu tun, da das ASP..®NET-Framework diese Registrierung verwenden wird, um die Ereignisse dieses Dienstes abzufeuern.StartAsync und StopAsync für IHostedService- - ).- Siehe unten IHostedlifeCycleService ist nur eine detailliertere Version von IHostedService-.
/// <summary>
/// Defines methods for objects that are managed by the host.
/// </summary>
public interface IHostedService
{
/// <summary>
/// Triggered when the application host is ready to start the service.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous Start operation.</returns>
Task StartAsync(CancellationToken cancellationToken);
/// <summary>
/// Triggered when the application host is performing a graceful shutdown.
/// </summary>
/// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous Stop operation.</returns>
Task StopAsync(CancellationToken cancellationToken);
}
namespace Microsoft.Extensions.Hosting
{
/// <summary>
/// Defines methods that are run before or after
/// <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StartAsync(System.Threading.CancellationToken)" /> and
/// <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" />.
/// </summary>
public interface IHostedLifecycleService : IHostedService
{
/// <summary>
/// Triggered before <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StartAsync(System.Threading.CancellationToken)" />.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task StartingAsync(CancellationToken cancellationToken);
/// <summary>
/// Triggered after <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StartAsync(System.Threading.CancellationToken)" />.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task StartedAsync(CancellationToken cancellationToken);
/// <summary>
/// Triggered before <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" />.
/// </summary>
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task StoppingAsync(CancellationToken cancellationToken);
/// <summary>
/// Triggered after <see cref="M:Microsoft.Extensions.Hosting.IHostedService.StopAsync(System.Threading.CancellationToken)" />.
/// </summary>
/// <param name="cancellationToken">Indicates that the stop process has been aborted.</param>
/// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation.</returns>
Task StoppedAsync(CancellationToken cancellationToken);
}
}
Wie Sie sicherstellen können, dass Ihr IHostedService eine einzige Instanz ist
Schnittstellenansatz
Der Interface-Ansatz könnte je nach Szenario einfacher sein. IHostedService und fügen Sie dann eine Methode zu dieser Schnittstelle hinzu, die Sie von Ihrem Controller aus anrufen können.
HINWEIS:-Sie müssen es immer noch als HostedService in ASP..-NET hinzufügen, damit der Dienst tatsächlich ausgeführt werden kann.
public interface IEmailSenderHostedService : IHostedService, IDisposable
{
Task SendEmailAsync(BaseEmailModel message);
}
Alles was wir dann tun müssen, ist dies als Singleton zu registrieren und diese dann in unserem Controller verwenden.
services.AddSingleton<IEmailSenderHostedService, EmailSenderHostedService>();
services.AddHostedService<IEmailSenderHostedService>(provider => provider.GetRequiredService<IEmailSenderHostedService>());
ASP-.-NET wird sehen, dass dies hat die richtige Schnittstelle dekoriert und wird diese Registrierung verwenden, um die laufen IHostedService.
Methodenansatz für die Fabrik
Eine andere, um sicherzustellen, dass Ihre IHostedService ist eine einzige Instanz ist, um die AddSingleton Methode, um Ihren Service zu registrieren dann übergeben Sie die IHostedService Registrierung als Fabrikationsmethode (MSK) Dies sorgt dafür, dass während der gesamten Lebensdauer der Anwendung nur eine Instanz Ihres Dienstes erstellt und verwendet wird.
- A Fabrik Methode ist nur eine fantasievolle Art, eine Methode zu sagen, die eine Instanz eines Objekts erzeugt.
services.AddSingleton<EmailSenderHostedService>();
services.AddHostedService(provider => provider.GetRequiredService<EmailSenderHostedService>());
So wie Sie hier sehen, registriere ich zuerst meine IHostedService ](-oder IHostedLifeCycleServiceAls Singleton und dann benutze ich die AddHostedService Methode, um den Service als Fabrikmethode zu registrieren.Dies stellt sicher, dass nur eine Instanz des Dienstes während der gesamten Lebensdauer der Anwendung erstellt und verwendet wird.
Schlussfolgerung
Wie üblich ist es ,' , ein paar Möglichkeiten, eine Katze zu häuten , die Fabrik Methode Ansatz ist auch ein guter Weg, um sicherzustellen, dass Ihr Service ist eine einzige Instanz , . , It .' , bis zu Ihnen, welche Annäherung Sie nehmen , ?. , Ich hoffe, dieser Artikel hat Ihnen geholfen zu verstehen, wie Sie sicherstellen, dass Ihre IHostedService ist eine einzelne Instanz.