DMNelson32
DMNelson32

Reputation: 21

How to raise Event in HostedService and consume it in a Blazor Component?

i am building a BlazorServer-Side App und i try to Update one of my Components when a Event occurs in a HostedService.

The Problem is solved! Check the Comments for the Solution.

This is how i try to do it:

Configuration in Startup.cs:

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

WeatherForecastService:

public class WeatherForecastService : IHostedService
{
    private System.Timers.Timer timer = new System.Timers.Timer(10000);

    public delegate void EventHandler(object sender, EventArgs e);

    public event EventHandler NewWeather;

    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private void TimeOver(object sender, ElapsedEventArgs e)
    {
        NewWeather?.Invoke(this, null);        
    }

    public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
    {
        var rng = new Random();
        return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = startDate.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        }).ToArray());
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        timer.Elapsed += TimeOver;
        timer.AutoReset = true;
        timer.Start();
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

FetchData.razor:

@code {
private WeatherForecast[] forecasts;

protected override async Task OnInitializedAsync()
{
    forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    ForecastService.NewWeather += UpdateWeather;
}

private async void UpdateWeather(object sender, object args)
{
    forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    StateHasChanged();    
}
}

UpdateWeather() on the FetchData.razor never gets called. I am guessing the FetchData Component does not notice the event is fired because of some threading issue. But I dont konw yet what to do about it...

Your Help is appreciated. Best Regards

Upvotes: 1

Views: 853

Answers (1)

DMNelson32
DMNelson32

Reputation: 21

The Code above generates two Instances of the WeatherForecastService!

The Solution is to change the registration of the HostedService from: services.AddHostedService(); to: services.AddHostedService(sp => sp.GetRequiredService());

Upvotes: 1

Related Questions