Hosten von ASP.NET Core SignalR in Hintergrunddiensten

Von Dave Pringle und Brady Gaster

Dieser Artikel enthält Anleitungen für Folgendes:

  • Hosten von SignalR-Hubs mithilfe eines mit ASP.NET Core gehosteten Workerprozesses im Hintergrund
  • Senden von Nachrichten an verbundene Clients aus einem .NET Core BackgroundService

Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)

Aktivieren von SignalR beim Start der App

Das Hosten von ASP.NET Core SignalR-Hubs im Kontext eines Workerprozesses im Hintergrund ist identisch mit dem Hosten eines Hubs in einer ASP.NET Core-Web-App. In Program.cs werden durch das Aufrufen von builder.Services.AddSignalR die erforderlichen Dienste zur DI-Schicht (Dependency Injection) von ASP.NET Core hinzugefügt, um SignalR zu unterstützen. Die MapHub-Methode wird für WebApplicationapp aufgerufen, um die Hubendpunkte mit der ASP.NET Core-Anforderungspipeline zu verbinden.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR();
builder.Services.AddHostedService<Worker>();

var app = builder.Build();

app.MapHub<ClockHub>("/hubs/clock");

app.Run();

Im vorherigen Beispiel implementiert die ClockHub-Klasse die Hub<T>-Klasse, um einen stark typisierten Hub zu erstellen. ClockHub wurde in Program.cs konfiguriert, um auf Anforderungen am Endpunkt /hubs/clock zu reagieren.

Weitere Informationen zu stark typisierten Hubs finden Sie unter Verwenden von Hubs in SignalR für ASP.NET Core.

Hinweis

Diese Funktionalität ist nicht auf die Hub<T>-Klasse beschränkt. Jede Klasse, die von Hub erbt, z. B. DynamicHub, funktioniert.

public class ClockHub : Hub<IClock>
{
    public async Task SendTimeToClients(DateTime dateTime)
    {
        await Clients.All.ShowTime(dateTime);
    }
}

Die vom stark typisierten ClockHub verwendete Schnittstelle ist IClock.

public interface IClock
{
    Task ShowTime(DateTime currentTime);
}

Aufrufen eines SignalR-Hubs in einem Hintergrunddienst

Während des Starts wird die Worker-Klasse, ein BackgroundService, mithilfe von AddHostedService aktiviert.

builder.Services.AddHostedService<Worker>();

Da SignalR auch während der Startphase aktiviert wird, in der jeder Hub an einen individuellen Endpunkt in der HTTP-Anforderungspipeline von ASP.NET Core angefügt wird, wird jeder Hub durch IHubContext<T> auf dem Server dargestellt. Mithilfe der DI-Features von ASP.NET Core können andere Klassen, die von der Hostingschicht instanziiert werden, wie z. B. BackgroundService-Klassen, MVC-Controller-Klassen oder Razor-Seitenmodelle, Verweise auf serverseitige Hubs abrufen, indem sie in der Erstellungsphase Instanzen von IHubContext<ClockHub, IClock> akzeptieren.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHubContext<ClockHub, IClock> _clockHub;

    public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)
    {
        _logger = logger;
        _clockHub = clockHub;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {Time}", DateTime.Now);
            await _clockHub.Clients.All.ShowTime(DateTime.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

Da die ExecuteAsync-Methode im Hintergrunddienst iterativ aufgerufen wird, werden das aktuelle Datum und die Uhrzeit des Servers mithilfe der ClockHub-Methode an die verbundenen Clients gesendet.

Reagieren auf SignalR-Ereignisse mithilfe von Hintergrunddiensten

Wie eine Single-Page-App, die den JavaScript-Client für SignalR verwendet, oder eine .NET-Desktop-App, die den ASP.NET Core SignalR .NET-Client nutzt, kann auch eine BackgroundService- oder IHostedService-Implementierung verwendet werden, um sich mit SignalR-Hubs zu verbinden und auf Ereignisse zu reagieren.

Die ClockHubClient-Klasse implementiert die Schnittstellen IClock und IHostedService. Auf diese Weise kann sie beim Start aktiviert werden, um kontinuierlich ausgeführt zu werden und auf Hubereignisse des Servers zu reagieren.

public partial class ClockHubClient : IClock, IHostedService
{
}

Während der Initialisierung erstellt ClockHubClient eine Instanz von HubConnection und aktiviert die IClock.ShowTime-Methode als Handler für das ShowTime-Ereignis des Hubs.

private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)
{
    _logger = logger;
    
    _connection = new HubConnectionBuilder()
        .WithUrl(Strings.HubUrl)
        .Build();

    _connection.On<DateTime>(Strings.Events.TimeSent, ShowTime);
}

public Task ShowTime(DateTime currentTime)
{
    _logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

    return Task.CompletedTask;
}

In der IHostedService.StartAsync-Implementierung wird HubConnection asynchron gestartet.

public async Task StartAsync(CancellationToken cancellationToken)
{
    // Loop is here to wait until the server is running
    while (true)
    {
        try
        {
            await _connection.StartAsync(cancellationToken);

            break;
        }
        catch
        {
            await Task.Delay(1000, cancellationToken);
        }
    }
}

Während der IHostedService.StopAsync-Methode wird HubConnection asynchron verworfen.

public async Task StopAsync(CancellationToken cancellationToken)
{
    await _connection.DisposeAsync();
}

Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)

Aktivieren von SignalR beim Start

Das Hosten von ASP.NET Core SignalR-Hubs im Kontext eines Workerprozesses im Hintergrund ist identisch mit dem Hosten eines Hubs in einer ASP.NET Core-Web-App. In der Startup.ConfigureServices-Methode werden durch das Aufrufen von services.AddSignalR die erforderlichen Dienste zur DI-Schicht (Dependency Injection) von ASP.NET Core hinzugefügt, um SignalR zu unterstützen. In Startup.Configure wird die MapHub-Methode im UseEndpoints-Rückruf aufgerufen, um die Hubendpunkte mit der ASP.NET Core-Anforderungspipeline zu verbinden.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSignalR();
        services.AddHostedService<Worker>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHub<ClockHub>("/hubs/clock");
        });
    }
}

Im vorherigen Beispiel implementiert die ClockHub-Klasse die Hub<T>-Klasse, um einen stark typisierten Hub zu erstellen. Der ClockHub wurde in der Startup-Klasse konfiguriert, um auf Anforderungen am Endpunkt /hubs/clock zu reagieren.

Weitere Informationen zu stark typisierten Hubs finden Sie unter Verwenden von Hubs in SignalR für ASP.NET Core.

Hinweis

Diese Funktionalität ist nicht auf die Hub<T>-Klasse beschränkt. Jede Klasse, die von Hub erbt, z. B. DynamicHub, funktioniert.

public class ClockHub : Hub<IClock>
{
    public async Task SendTimeToClients(DateTime dateTime)
    {
        await Clients.All.ShowTime(dateTime);
    }
}

Die vom stark typisierten ClockHub verwendete Schnittstelle ist IClock.

public interface IClock
{
    Task ShowTime(DateTime currentTime);
}

Aufrufen eines SignalR-Hubs in einem Hintergrunddienst

Während des Starts wird die Worker-Klasse, ein BackgroundService, mithilfe von AddHostedService aktiviert.

services.AddHostedService<Worker>();

Da SignalR auch während der Startup-Phase aktiviert wird, in der jeder Hub an einen individuellen Endpunkt in der HTTP-Anforderungspipeline von ASP.NET Core angefügt wird, wird jeder Hub durch IHubContext<T> auf dem Server dargestellt. Mithilfe der DI-Features von ASP.NET Core können andere Klassen, die von der Hostingschicht instanziiert werden, wie z. B. BackgroundService-Klassen, MVC-Controller-Klassen oder Razor-Seitenmodelle, Verweise auf serverseitige Hubs abrufen, indem sie in der Erstellungsphase Instanzen von IHubContext<ClockHub, IClock> akzeptieren.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHubContext<ClockHub, IClock> _clockHub;

    public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)
    {
        _logger = logger;
        _clockHub = clockHub;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {Time}", DateTime.Now);
            await _clockHub.Clients.All.ShowTime(DateTime.Now);
            await Task.Delay(1000);
        }
    }
}

Da die ExecuteAsync-Methode im Hintergrunddienst iterativ aufgerufen wird, werden das aktuelle Datum und die Uhrzeit des Servers mithilfe der ClockHub-Methode an die verbundenen Clients gesendet.

Reagieren auf SignalR-Ereignisse mithilfe von Hintergrunddiensten

Wie eine Single-Page-App, die den JavaScript-Client für SignalR verwendet, oder eine .NET-Desktop-App, die den ASP.NET Core SignalR .NET-Client nutzt, kann auch eine BackgroundService- oder IHostedService-Implementierung verwendet werden, um sich mit SignalR-Hubs zu verbinden und auf Ereignisse zu reagieren.

Die ClockHubClient-Klasse implementiert die Schnittstellen IClock und IHostedService. Auf diese Weise kann sie beim Startup aktiviert werden, um kontinuierlich ausgeführt zu werden und auf Hubereignisse auf dem Server zu reagieren.

public partial class ClockHubClient : IClock, IHostedService
{
}

Während der Initialisierung erstellt ClockHubClient eine Instanz von HubConnection und aktiviert die IClock.ShowTime-Methode als Handler für das ShowTime-Ereignis des Hubs.

private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)
{
    _logger = logger;
    
    _connection = new HubConnectionBuilder()
        .WithUrl(Strings.HubUrl)
        .Build();

    _connection.On<DateTime>(Strings.Events.TimeSent, ShowTime);
}

public Task ShowTime(DateTime currentTime)
{
    _logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

    return Task.CompletedTask;
}

In der IHostedService.StartAsync-Implementierung wird HubConnection asynchron gestartet.

public async Task StartAsync(CancellationToken cancellationToken)
{
    // Loop is here to wait until the server is running
    while (true)
    {
        try
        {
            await _connection.StartAsync(cancellationToken);

            break;
        }
        catch
        {
            await Task.Delay(1000);
        }
    }
}

Während der IHostedService.StopAsync-Methode wird HubConnection asynchron verworfen.

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

Beispielcode anzeigen oder herunterladen (Vorgehensweise zum Herunterladen)

Aktivieren von SignalR beim Start

Das Hosten von ASP.NET Core SignalR-Hubs im Kontext eines Workerprozesses im Hintergrund ist identisch mit dem Hosten eines Hubs in einer ASP.NET Core-Web-App. In der Startup.ConfigureServices-Methode werden durch das Aufrufen von services.AddSignalR die erforderlichen Dienste zur DI-Schicht (Dependency Injection) von ASP.NET Core hinzugefügt, um SignalR zu unterstützen. In Startup.Configure wird die UseSignalR-Methode aufgerufen, um die Hubendpunkte mit der ASP.NET Core-Anforderungspipeline zu verbinden.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSignalR();
        services.AddHostedService<Worker>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseSignalR((routes) =>
        {
            routes.MapHub<ClockHub>("/hubs/clock");
        });
    }
}

Im vorherigen Beispiel implementiert die ClockHub-Klasse die Hub<T>-Klasse, um einen stark typisierten Hub zu erstellen. Der ClockHub wurde in der Startup-Klasse konfiguriert, um auf Anforderungen am Endpunkt /hubs/clock zu reagieren.

Weitere Informationen zu stark typisierten Hubs finden Sie unter Verwenden von Hubs in SignalR für ASP.NET Core.

Hinweis

Diese Funktionalität ist nicht auf die Hub<T>-Klasse beschränkt. Jede Klasse, die von Hub erbt, z. B. DynamicHub, funktioniert.

public class ClockHub : Hub<IClock>
{
    public async Task SendTimeToClients(DateTime dateTime)
    {
        await Clients.All.ShowTime(dateTime);
    }
}

Die vom stark typisierten ClockHub verwendete Schnittstelle ist IClock.

public interface IClock
{
    Task ShowTime(DateTime currentTime);
}

Aufrufen eines SignalR-Hubs in einem Hintergrunddienst

Während des Starts wird die Worker-Klasse, ein BackgroundService, mithilfe von AddHostedService aktiviert.

services.AddHostedService<Worker>();

Da SignalR auch während der Startup-Phase aktiviert wird, in der jeder Hub an einen individuellen Endpunkt in der HTTP-Anforderungspipeline von ASP.NET Core angefügt wird, wird jeder Hub durch IHubContext<T> auf dem Server dargestellt. Mithilfe der DI-Features von ASP.NET Core können andere Klassen, die von der Hostingschicht instanziiert werden, wie z. B. BackgroundService-Klassen, MVC-Controller-Klassen oder Razor-Seitenmodelle, Verweise auf serverseitige Hubs abrufen, indem sie in der Erstellungsphase Instanzen von IHubContext<ClockHub, IClock> akzeptieren.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IHubContext<ClockHub, IClock> _clockHub;

    public Worker(ILogger<Worker> logger, IHubContext<ClockHub, IClock> clockHub)
    {
        _logger = logger;
        _clockHub = clockHub;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {Time}", DateTime.Now);
            await _clockHub.Clients.All.ShowTime(DateTime.Now);
            await Task.Delay(1000);
        }
    }
}

Da die ExecuteAsync-Methode im Hintergrunddienst iterativ aufgerufen wird, werden das aktuelle Datum und die Uhrzeit des Servers mithilfe der ClockHub-Methode an die verbundenen Clients gesendet.

Reagieren auf SignalR-Ereignisse mithilfe von Hintergrunddiensten

Wie eine Single-Page-App, die den JavaScript-Client für SignalR verwendet, oder eine .NET-Desktop-App, die den ASP.NET Core SignalR .NET-Client nutzt, kann auch eine BackgroundService- oder IHostedService-Implementierung verwendet werden, um sich mit SignalR-Hubs zu verbinden und auf Ereignisse zu reagieren.

Die ClockHubClient-Klasse implementiert die Schnittstellen IClock und IHostedService. Auf diese Weise kann sie beim Startup aktiviert werden, um kontinuierlich ausgeführt zu werden und auf Hubereignisse auf dem Server zu reagieren.

public partial class ClockHubClient : IClock, IHostedService
{
}

Während der Initialisierung erstellt ClockHubClient eine Instanz von HubConnection und aktiviert die IClock.ShowTime-Methode als Handler für das ShowTime-Ereignis des Hubs.

private readonly ILogger<ClockHubClient> _logger;
private HubConnection _connection;

public ClockHubClient(ILogger<ClockHubClient> logger)
{
    _logger = logger;
    
    _connection = new HubConnectionBuilder()
        .WithUrl(Strings.HubUrl)
        .Build();

    _connection.On<DateTime>(Strings.Events.TimeSent, 
        dateTime => _ = ShowTime(dateTime));
}

public Task ShowTime(DateTime currentTime)
{
    _logger.LogInformation("{CurrentTime}", currentTime.ToShortTimeString());

    return Task.CompletedTask;
}

In der IHostedService.StartAsync-Implementierung wird HubConnection asynchron gestartet.

public async Task StartAsync(CancellationToken cancellationToken)
{
    // Loop is here to wait until the server is running
    while (true)
    {
        try
        {
            await _connection.StartAsync(cancellationToken);

            break;
        }
        catch
        {
            await Task.Delay(1000);
        }
    }
}

Während der IHostedService.StopAsync-Methode wird HubConnection asynchron verworfen.

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

Zusätzliche Ressourcen