# अपने IHostedService (or IHosedLifecycleService) सुनिश्चित करना एक एकल इंस्टैंस है

<!--category-- ASP.NET -->
<datetime class="hidden">2024-08-22T16:08</datetime>

## परिचय

यह एक मूर्ख छोटा लेख है क्योंकि मैं कैसे सुनिश्चित करने के बारे में थोड़ा भ्रमित था कि मेरा `IHostedService` एक एकल उदाहरण था। <s> मैंने सोचा कि यह वास्तव में से थोड़ा अधिक जटिल था।

में [पूर्व अनुच्छेद](/blog/addingasyncsendingforemails), हम कैसे एक पृष्ठभूमि सेवा का उपयोग करने के लिए बनाना शामिल किया `IHostedService` ईमेल भेजने के लिए इंटरफेस. इस लेख में यह सुनिश्चित करने के लिए कैसे कवर किया जाएगा कि आपका `IHostedService` एक एकल इंस्टैंस है
यह कुछ लोगों के लिए स्पष्ट हो सकता है, लेकिन यह अन्यों के लिए नहीं है।

[TOC]

## यह एक मुद्दा क्यों है

अच्छी तरह से यह एक मुद्दा के रूप में अधिकांश लेख बाहर इन कवर कैसे उपयोग करने के लिए है `IHostedService` लेकिन वे नहीं ' कैसे सुनिश्चित करने के लिए कि सेवा एक एकल इंस्टैंस है सुनिश्चित करना शामिल नहीं करता है।

मेरा मतलब क्या है?

```csharp
  services.AddHostedService(EmailSenderHostedService);
```

जो करता है यह बैकएण्ड कोड में कॉल करता है

```csharp
public static IServiceCollection AddHostedService<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] THostedService>(this IServiceCollection services)
            where THostedService : class, IHostedService
        {
            services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, THostedService>());

            return services;
        }

```

जो ठीक और सुंदर है लेकिन क्या अगर आप इस सेवा से सीधे एक नया संदेश पोस्ट करना चाहते हैं `Controller` कार्य

```csharp

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");
    }
   }
```

या आप एक इंटरफेस बनाने की जरूरत है जो स्वयं लागू करता है `IHostedService` तो उस पर विधि में कॉल करें या आपको यह सुनिश्चित करने की जरूरत है कि सेवा एक एकल इंस्टैंस है

### IHostedServiceComment

आप' यहाँ नोट करेंगे कि यह एक सेवा के रूप में पंजीकृत करता है `IHostedService`यह इस सेवा के जीवन चक्र प्रबंधन से संबंधित है क्योंकि ASP.NET फ्रेमवर्क इस पंजीकरण का उपयोग इस सेवा की घटनाओं को निष्क्रिय करने के लिए करेगा`StartAsync` और `StopAsync` के लिए IHostedService). नीचे देखें `IHostedlifeCycleService` सिर्फ एक अधिक विस्तृत संस्करण है IHostedService.

```csharp
  /// <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);
  }
}
```

## यह सुनिश्चित करने के लिए कि आपका IHostedService एक एकल इंस्टैंस है

### इंटरफेस दृष्टिकोण

इंटरफेस दृष्टिकोण आपके परिदृश्य के आधार पर सरल हो सकता है `IHostedService` और फिर उस इंटरफेस में एक विधि जोड़ें कि आप अपने नियंत्रक से कॉल कर सकते हैं

**नोट: आपको अभी भी इसे ASP में होस्टेड सर्विस के रूप में जोड़ने की जरूरत है**

```csharp
    public interface IEmailSenderHostedService : IHostedService, IDisposable
    {
        Task SendEmailAsync(BaseEmailModel message);
    }
```

तब हमें बस एक एकलटन के रूप में इसे पंजीकृत करने की जरूरत है और फिर हमारे नियंत्रक में इस का उपयोग करें

```csharp
             services.AddSingleton<IEmailSenderHostedService, EmailSenderHostedService>();
        services.AddHostedService<IEmailSenderHostedService>(provider => provider.GetRequiredService<IEmailSenderHostedService>());
        
```

ASP.NET देखेगा कि यह सही इंटरफेस सजा हुआ है और इस पंजीकरण को चलाने के लिए उपयोग करेगा `IHostedService`.

### फैक्टरी विधि दृष्टिकोण

एक और सुनिश्चित करने के लिए कि आपके `IHostedService` एक एकल उदाहरण है कि उपयोग करने के लिए है `AddSingleton` विधि अपना सेवा पंजीकृत करने के लिए फिर पास `IHostedService` एक ' फैक्टरी विधि के रूप में पंजीकरण

* ए *कारखाना* विधि, एक वस्तु का एक उदाहरण बनाने के लिए एक विधि कहने की सिर्फ एक फैशन तरीका है

```csharp
        services.AddSingleton<EmailSenderHostedService>();
        services.AddHostedService(provider => provider.GetRequiredService<EmailSenderHostedService>());
```

तो जैसा कि आप यहाँ देख रहे हैं मैं पहले अपने पंजीकरण `IHostedService` ( `IHostedLifeCycleService`) एक एकलटन के रूप में और फिर मैं उपयोग करता हूँ `AddHostedService` सेवा को फैक्टरी विधि के रूप में पंजीकृत करने की विधि

## अंत में

जैसा कि आमतौर पर है वहाँ' एक बिल्ली को त्वचा करने के लिए एक दो तरीके हैं-. फैक्टरी विधि दृष्टिकोण भी यह सुनिश्चित करने का एक अच्छा तरीका है कि आपका सेवा एक एकल उदाहरण है। `IHostedService` एक एकल इंस्टैंस है