Damn Vegetables
Damn Vegetables

Reputation: 12474

Blazor: How to get the hosted service instance?

I added a background service that periodically does something, like the official sample.

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddHostedService<TimedHostedService>(); <-- here
    services.AddSingleton<WeatherForecastService>();
}

The TimedHostedService has StartAsync and StopAsync. Ultimately, I want to call these in the web browser.

In the FetchData.razor file in the default scaffolding, I tried to refer that service directly, but that did not work. So, I added Start and Stop method to the WeatherForecastService and called them on the click event.

<button @onclick="()=> { ForecastService.Stop(); }">Stop</button>

Now, the problem is, that I don't know how to get the running instance of TimedHostedService in the Stop method of WeatherForecastService.

public class WeatherForecastService
{
....
    public void Stop()
    {
        //how to get TimedHostedService instance?
    }
....
}

I have tried using dependency injection to get the service provider, but GetService returned null.

IServiceProvider sp;
public WeatherForecastService(IServiceProvider sp)
{
    this.sp = sp;
}

public void Stop()
{
    var ts = sp.GetService(typeof(TimedHostedService)) as TimedHostedService;
    ts.StopAsync(new CancellationToken());
}

Upvotes: 4

Views: 9334

Answers (2)

Joel
Joel

Reputation: 11

Share a singleton service between your UI and your Hosted service. Manipulate the values in the UI and consume the values in the Hosted service. Set up a timer in the Hosted Service.

Whenever I've done this, I set a property in the singleton like "IsStop". Then I use the singleton as a data transport. On the view, set the singleton.IsStop value to true. The next time the HostedService cycles I check the singleton.IsStop where I kill the timer. I typically include a RunFrequency and IsPause property also to define how often the timer should run and if I want to keep the timer in place but pause the logic execution.

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273494

I question the wisdom of manipulating the service from the GUI but if you're sure you want this then it's about how to register that service.

In startup:

services.AddSingleton<TimedHostedService>();
services.AddHostedService(sp => sp.GetRequiredService<TimedHostedService>());

and then you can

@inject TimedHostedService TimedService

Upvotes: 8

Related Questions