Varmistetaan, että IHostedService ( tai IHosedLifecycleService) on yksi ainoa tapaus
Esitys
Tämä on typerä pieni artikkeli, koska olin hieman sekaantunut siihen, miten varmistaa IHostedService oli yksi tapaus. Luulin, että se oli hieman monimutkaisempi kuin se itse asiassa oli.
Siinä edellinen artikla, käsittelimme, miten luoda taustapalvelu IHostedService yhteys sähköpostien lähettämiseen. Tässä artiklassa käsitellään sitä, miten varmistetaan IHostedService on yksi tapaus.
Tämä saattaa olla itsestään selvää joillekin, mutta se ei ole itsestään selvä muille.
Miksi tämä on ongelma?
No se on ongelma, koska suurin osa artikloista näitä kattaa, miten käyttää IHostedService mutta niissä ei käsitellä sitä, miten varmistetaan, että palvelu on yksi instanssi. Tämä on tärkeää, koska te ette halua, että palvelujen useat instansit toimivat samanaikaisesti.
Mitä tarkoitan?
services.AddHostedService(EmailSenderHostedService);
Se kutsuu tähän backend-koodiin.
public static IServiceCollection AddHostedService<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THostedService>(this IServiceCollection services)
where THostedService : class, IHostedService
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, THostedService>());
return services;
}
Se on hienoa ja hienoa, mutta mitä jos haluatte lähettää uuden viestin suoraan tähän palveluun sanoen Controller toiminta?
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");
}
}
Ei tarvitse perustaa liittymää, joka itse panee toimeen IHostedService sitten kutsutte menetelmään sen perusteella tai teidän on varmistettava, että palvelu on yksi ainoa tapaus. jälkimmäinen on helpoin tapa tehdä tämä ( riippuu skenaariostanne, vaikka, Interface-menetelmän testaamista varten voi suosia
IHostedService
Teidän on huomattava, että se rekisteröi palvelun IHostedService, tämä liittyy tämän palvelun elinkaaren hallintaan, sillä ASP: n järjestelmässä käytetään tätä rekisteröintiä kyseisen palvelun tapahtumien sammuttamiseksi.StartAsync ja StopAsync IHostedService:lle). Ks. jäljempänä, IHostedlifeCycleService on vain yksityiskohtaisempi versio IHostedServicesta.
/// <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);
}
}
Miten varmistaa, että IHostedService on yksi tapaus
Interface-lähestymistapa
Interface-lähestymistapa voi olla yksinkertaisempi riippumatta skenaariostanne. IHostedService ja sen jälkeen liittää menetelmän yhteenliittymään, jota voi kutsua valvontakoneeltanne.
PANEE MERKILLE: Teidän on vielä lisättävä se ASP:n HostedService-palveluksi.NET, jotta palvelu todellakin käynnistettäisiin
public interface IEmailSenderHostedService : IHostedService, IDisposable
{
Task SendEmailAsync(BaseEmailModel message);
}
Sen jälkeen tarvitsemme vain rekisteröidä sen yhdeksi tonniksi ja käyttää sitä omassa valvontajärjestelmässämme.
services.AddSingleton<IEmailSenderHostedService, EmailSenderHostedService>();
services.AddHostedService<IEmailSenderHostedService>(provider => provider.GetRequiredService<IEmailSenderHostedService>());
ASP.NET huomaa, että sillä on oikea interfejs ja käyttää tätä rekisteröintiä IHostedService.
Teollisuusmenetelmän lähestymistapa
Toinen varmistaa, että IHostedService on vain yksi tapaus käyttää AddSingleton menetelmä rekisteröidä palvelunne ja sen jälkeen toimittaa IHostedService rekisteröinti 'teollinen menetelmäM SK1 Tämä varmistaa, että vain yksi palvelunne instanssi on luotu ja käytetty koko soveltamisen ajan
- A tehdas menetelmä on vain hieno tapa sanoa menetelmä, joka luo objektin instanssin.
services.AddSingleton<EmailSenderHostedService>();
services.AddHostedService(provider => provider.GetRequiredService<EmailSenderHostedService>());
Kuten näette, rekisteröin ensin IHostedService ( tai IHostedLifeCycleService) yksitonisena ja sen jälkeen käytän AddHostedService menetelmä palvelun rekisteröimiseksi tehtaaksi menetelmä. Näin varmistetaan, että vain yksi palvelun instanssi luodaan ja käytetään koko soveltamisen ajan
Päätelmissä
Kuten tavallista, on olemassa joitakin tapoja peitellä kissaa. Tehtaiden menetelmän lähestymistapa on myös hyvä tapa varmistaa, että palvelunne on yksi tapaus. IHostedService on yksi tapaus.