Héberger ASP.NET Core SignalR dans les services d'arrière-plan

Par Dave Pringle et Brady Gaster

Cet article fournit des conseils pour :

  • Hosting SignalR Hubs à l'aide d'un processus de travail en arrière-plan hébergé avec ASP.NET Core.
  • Envoi de messages aux clients connectés à partir d'un .NET Core BackgroundService.

Afficher ou télécharger l’exemple de code(procédure de téléchargement)

Activer SignalR au démarrage de l’application

Hosting ASP.NET Core SignalR Hubs dans le contexte d'un processus de travail en arrière-plan est identique à l'hébergement d'un concentrateur dans une application Web ASP.NET Core. Dans Program.cs, l'appel builder.Services.AddSignalR ajoute les services requis à la couche ASP.NET Core Dependency Injection (DI) pour prendre en charge SignalR. La méthode MapHub est appelée sur WebApplicationapp pour connecter les points de terminaison Hub dans le pipeline de requêtes ASP.NET Core.

var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

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

app.Run();

Dans l'exemple précédent, la classe ClockHub implémente la classe Hub<T> pour créer un Hub fortement typé. Le ClockHub a été configuré Program.cs pour répondre aux demandes au point de terminaison /hubs/clock.

Pour plus d'informations sur les Hubs fortement typés, consultez Utiliser des hubs SignalR dans pour ASP.NET Core.

Notes

Cette fonctionnalité n'est pas limitée à la classe Hub<T>. Toute classe qui hérite de Hub, telle que DynamicHub, fonctionne.

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

L'interface utilisée par les fortement typés ClockHub est l'interface IClock.

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

Appeler un hub SignalR à partir d'un service en arrière-plan

Au démarrage, la classe Worker, un BackgroundService, est activée à l'aide de AddHostedService.

builder.Services.AddHostedService<Worker>();

Comme SignalR est également activé pendant la phase de démarrage, dans laquelle chaque hub est attaché à un point de terminaison individuel dans le pipeline de requêtes HTTP d'ASP.NET Core, chaque hub est représenté par un IHubContext<T> sur le serveur. À l'aide des fonctionnalités DI d'ASP.NET Core, d'autres classes instanciées par la couche d'hébergement, telles que les classes BackgroundService, les classes de contrôleur MVC ou les modèles de page Razor, peuvent obtenir des références aux concentrateurs côté serveur en acceptant des instances de IHubContext<ClockHub, IClock> pendant la construction.

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

Comme la méthode ExecuteAsync est appelée de manière itérative dans le service d'arrière-plan, la date et l'heure actuelles du serveur sont envoyées aux clients connectés à l'aide de l'extension ClockHub.

Réagissez aux événements SignalR avec des services d'arrière-plan

Comme une application monopage utilisant le client JavaScript pour SignalR, ou une application de bureau .NET utilisant le client ASP.NET Core SignalR .NET, une implémentation BackgroundService ou IHostedService peut également être utilisée pour se connecter aux hubs SignalR et répondre aux événements.

La classe ClockHubClient implémente à la fois l'interface IClock et l'interface IHostedService. De cette façon, il peut être activé au démarrage pour s'exécuter en continu et répondre aux événements du Hub à partir du serveur.

public partial class ClockHubClient : IClock, IHostedService
{
}

Lors de l'initialisation, le ClockHubClient crée une instance d’un HubConnection et active la méthode IClock.ShowTime en tant que gestionnaire de l'événement du Hub ShowTime.

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;
}

Dans l’implémentation IHostedService.StartAsync, le HubConnection est démarré de manière asynchrone.

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

Pendant la méthode IHostedService.StopAsync, le HubConnection est supprimé de manière asynchrone.

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

Afficher ou télécharger l’exemple de code(procédure de téléchargement)

Activer SignalR au démarrage

Hosting ASP.NET Core SignalR Hubs dans le contexte d'un processus de travail en arrière-plan est identique à l'hébergement d'un concentrateur dans une application Web ASP.NET Core. Dans la méthode Startup.ConfigureServices, l'appel services.AddSignalR s’ajoute les services requis à la couche ASP.NET Core Dependency Injection (DI) pour prendre en charge SignalR. Dans Startup.Configure, la méthode MapHub est appelée dans le rappel UseEndpoints pour connecter les points de terminaison Hub dans le pipeline de requêtes ASP.NET Core.

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

Dans l'exemple précédent, la classe ClockHub implémente la classe Hub<T> pour créer un Hub fortement typé. Le ClockHub a été configuré dans la classe Startup pour répondre aux requêtes au point de terminaison /hubs/clock.

Pour plus d'informations sur les Hubs fortement typés, consultez Utiliser des hubs SignalR dans pour ASP.NET Core.

Notes

Cette fonctionnalité n'est pas limitée à la classe Hub<T>. Toute classe qui hérite de Hub, telle que DynamicHub, fonctionne.

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

L'interface utilisée par les fortement typés ClockHub est l'interface IClock.

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

Appeler un hub SignalR à partir d'un service en arrière-plan

Au démarrage, la classe Worker, un BackgroundService, est activée à l'aide de AddHostedService.

services.AddHostedService<Worker>();

Étant SignalR donné que est également activé pendant la phase Startup, dans laquelle chaque Hub est attaché à un point de terminaison individuel dans le pipeline de requêtes HTTP d'ASP.NET Core, chaque Hub est représenté par un IHubContext<T> sur le serveur. À l'aide des fonctionnalités DI d'ASP.NET Core, d'autres classes instanciées par la couche d'hébergement, telles que les classes BackgroundService, les classes de contrôleur MVC ou les modèles de page Razor, peuvent obtenir des références aux concentrateurs côté serveur en acceptant des instances de IHubContext<ClockHub, IClock> pendant la construction.

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

Comme la méthode ExecuteAsync est appelée de manière itérative dans le service d'arrière-plan, la date et l'heure actuelles du serveur sont envoyées aux clients connectés à l'aide de l'extension ClockHub.

Réagissez aux événements SignalR avec des services d'arrière-plan

Comme une application monopage utilisant le client JavaScript pour SignalR, ou une application de bureau .NET utilisant le client ASP.NET Core SignalR .NET, une implémentation BackgroundService ou IHostedService peut également être utilisée pour se connecter aux hubs SignalR et répondre aux événements.

La classe ClockHubClient implémente à la fois l'interface IClock et l'interface IHostedService. De cette façon, il peut être activé pendant Startup pour exécuter en continu et répondre aux événements du Hub à partir du serveur.

public partial class ClockHubClient : IClock, IHostedService
{
}

Lors de l'initialisation, le ClockHubClient crée une instance d’un HubConnection et active la méthode IClock.ShowTime en tant que gestionnaire de l'événement du Hub ShowTime.

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;
}

Dans l’implémentation IHostedService.StartAsync, le HubConnection est démarré de manière asynchrone.

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

Pendant la méthode IHostedService.StopAsync, le HubConnection est supprimé de manière asynchrone.

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

Afficher ou télécharger l’exemple de code(procédure de téléchargement)

Activer SignalR au démarrage

Hosting ASP.NET Core SignalR Hubs dans le contexte d'un processus de travail en arrière-plan est identique à l'hébergement d'un concentrateur dans une application Web ASP.NET Core. Dans la méthode Startup.ConfigureServices, l'appel services.AddSignalR s’ajoute les services requis à la couche ASP.NET Core Dependency Injection (DI) pour prendre en charge SignalR. Dans Startup.Configure, la méthode UseSignalR est appelée pour connecter le ou les points de terminaison Hub dans le pipeline de requêtes ASP.NET Core.

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

Dans l'exemple précédent, la classe ClockHub implémente la classe Hub<T> pour créer un Hub fortement typé. Le ClockHub a été configuré dans la classe Startup pour répondre aux requêtes au point de terminaison /hubs/clock.

Pour plus d'informations sur les Hubs fortement typés, consultez Utiliser des hubs SignalR dans pour ASP.NET Core.

Notes

Cette fonctionnalité n'est pas limitée à la classe Hub<T>. Toute classe qui hérite de Hub, telle que DynamicHub, fonctionne.

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

L'interface utilisée par les fortement typés ClockHub est l'interface IClock.

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

Appeler un hub SignalR à partir d'un service en arrière-plan

Au démarrage, la classe Worker, un BackgroundService, est activée à l'aide de AddHostedService.

services.AddHostedService<Worker>();

Étant SignalR donné que est également activé pendant la phase Startup, dans laquelle chaque Hub est attaché à un point de terminaison individuel dans le pipeline de requêtes HTTP d'ASP.NET Core, chaque Hub est représenté par un IHubContext<T> sur le serveur. À l'aide des fonctionnalités DI d'ASP.NET Core, d'autres classes instanciées par la couche d'hébergement, telles que les classes BackgroundService, les classes de contrôleur MVC ou les modèles de page Razor, peuvent obtenir des références aux concentrateurs côté serveur en acceptant des instances de IHubContext<ClockHub, IClock> pendant la construction.

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

Comme la méthode ExecuteAsync est appelée de manière itérative dans le service d'arrière-plan, la date et l'heure actuelles du serveur sont envoyées aux clients connectés à l'aide de l'extension ClockHub.

Réagissez aux événements SignalR avec des services d'arrière-plan

Comme une application monopage utilisant le client JavaScript pour SignalR, ou une application de bureau .NET utilisant le client ASP.NET Core SignalR .NET, une implémentation BackgroundService ou IHostedService peut également être utilisée pour se connecter aux hubs SignalR et répondre aux événements.

La classe ClockHubClient implémente à la fois l'interface IClock et l'interface IHostedService. De cette façon, il peut être activé pendant Startup pour exécuter en continu et répondre aux événements du Hub à partir du serveur.

public partial class ClockHubClient : IClock, IHostedService
{
}

Lors de l'initialisation, le ClockHubClient crée une instance d’un HubConnection et active la méthode IClock.ShowTime en tant que gestionnaire de l'événement du Hub ShowTime.

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;
}

Dans l’implémentation IHostedService.StartAsync, le HubConnection est démarré de manière asynchrone.

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

Pendant la méthode IHostedService.StopAsync, le HubConnection est supprimé de manière asynchrone.

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

Ressources supplémentaires