共用方式為


在背景服務中託管 ASP.NET Core SignalR

作者:Dave PringleBrady Gaster

本文提供下列項目的指導:

  • 使用裝載 ASP.NET Core 的背景背景工作處理序,裝載 SignalR 中樞。
  • 從 .NET Core BackgroundService,將訊息傳送至連線的用戶端。

檢視或下載範例程式碼(如何下載)

在應用程式啟動時啟用 SignalR

在背景背景工作處理序的內容中裝載 ASP.NET Core SignalR 中樞,與在 ASP.NET Core Web 應用程式中裝載的方式相同。 在 Program.cs 中,呼叫 builder.Services.AddSignalR 會將必要的服務新增至 ASP.NET Core 相依性插入 (DI) 層,以支援 SignalR。 在 WebApplicationapp 上呼叫了 MapHub 方法,以連線 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();

在上述範例中,類別 ClockHub 會實作 Hub<T> 類別來建立強型別中樞。 已在 Program.cs 中設定 ClockHub,以回應端點 /hubs/clock 的要求。

如需強型別中樞的詳細資訊,請參閱在適用於 SignalR 的 ASP.NET Core 中使用中樞

注意

這項功能不限於中樞<T> 類別。 繼承自中樞的任何類別 (例如 DynamicHub) 均適用。

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

強型別 ClockHub 所使用的介面是 IClock 介面。

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

從背景服務呼叫 SignalR 中樞

在啟動期間,將使用 AddHostedService 啟用 Worker 類別 BackgroundService

builder.Services.AddHostedService<Worker>();

由於在啟動階段也會啟用 SignalR,因此每個中樞都會附加至 ASP.NET Core HTTP 要求管線中的個別端點,因此每個中樞都會在伺服器上以 IHubContext<T> 來表示。 使用 ASP.NET Core 的 DI 功能,裝載層所具現化的其他類別 (例如 BackgroundService 類別、MVC 控制器類別或 Razor 頁面模型) 可以透過在建構期間接受 IHubContext<ClockHub, IClock> 執行個體來取得伺服器端中樞的參考。

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

當背景服務中反覆呼叫 ExecuteAsync 方法時,伺服器目前的日期和時間會使用 ClockHub傳送至連線的用戶端。

使用背景服務回應 SignalR 事件

如同使用 SignalR 之 JavaScript 用戶端的單頁應用程式,或使用 ASP.NET Core SignalR .NET 用戶端的 .NET 傳統型應用程式一樣,BackgroundServiceIHostedService 實作也可用於連線至 SignalR 中樞並回應事件。

ClockHubClient 類別會同時實作 IClock 介面和 IHostedService 介面。 如此一來,就可以在啟始期間啟用,以持續執行,並從伺服器回應中樞事件。

public partial class ClockHubClient : IClock, IHostedService
{
}

初始化期間,ClockHubClient 會建立 HubConnection 的執行個體,並啟用 IClock.ShowTime 方法作為中樞 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;
}

IHostedService.StartAsync 實作中,會以非同步方式啟動 HubConnection

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

IHostedService.StopAsync 方法期間,HubConnection 會以非同步方式處置。

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

檢視或下載範例程式碼(如何下載)

在啟動時啟用 SignalR

在背景背景工作處理序的內容中裝載 ASP.NET Core SignalR 中樞,與在 ASP.NET Core Web 應用程式中裝載的方式相同。 在 Startup.ConfigureServices 方法中,呼叫 services.AddSignalR 會將必要的服務新增至 ASP.NET Core 相依性插入 (DI) 層,以支援 SignalR。 在 Startup.Configure 內,在 UseEndpoints 回呼中呼叫了 MapHub 方法,以連線 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");
        });
    }
}

在上述範例中,類別 ClockHub 會實作 Hub<T> 類別來建立強型別中樞。 已在 Startup 類別中設定 ClockHub,以回應端點 /hubs/clock 的要求。

如需強型別中樞的詳細資訊,請參閱在適用於 SignalR 的 ASP.NET Core 中使用中樞

注意

這項功能不限於中樞<T> 類別。 繼承自中樞的任何類別 (例如 DynamicHub) 均適用。

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

強型別 ClockHub 所使用的介面是 IClock 介面。

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

從背景服務呼叫 SignalR 中樞

在啟動期間,將使用 AddHostedService 啟用 Worker 類別 BackgroundService

services.AddHostedService<Worker>();

由於在 Startup 階段也會啟用,因此 SignalR 每個中樞都會附加至 ASP.NET Core HTTP 要求管線中的個別端點,因此每個中樞都會以伺服器上的 IHubContext<T> 來表示。 使用 ASP.NET Core 的 DI 功能,裝載層所具現化的其他類別 (例如 BackgroundService 類別、MVC 控制器類別或 Razor 頁面模型) 可以透過在建構期間接受 IHubContext<ClockHub, IClock> 執行個體來取得伺服器端中樞的參考。

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

當背景服務中反覆呼叫 ExecuteAsync 方法時,伺服器目前的日期和時間會使用 ClockHub傳送至連線的用戶端。

使用背景服務回應 SignalR 事件

如同使用 SignalR 之 JavaScript 用戶端的單頁應用程式,或使用 ASP.NET Core SignalR .NET 用戶端的 .NET 傳統型應用程式一樣,BackgroundServiceIHostedService 實作也可用於連線至 SignalR 中樞並回應事件。

ClockHubClient 類別會同時實作 IClock 介面和 IHostedService 介面。 如此一來,就可以在 Startup 期間啟用,以持續執行,並從伺服器回應中樞事件。

public partial class ClockHubClient : IClock, IHostedService
{
}

初始化期間,ClockHubClient 會建立 HubConnection 的執行個體,並啟用 IClock.ShowTime 方法作為中樞 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;
}

IHostedService.StartAsync 實作中,會以非同步方式啟動 HubConnection

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

IHostedService.StopAsync 方法期間,HubConnection 會以非同步方式處置。

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

檢視或下載範例程式碼(如何下載)

在啟動時啟用 SignalR

在背景背景工作處理序的內容中裝載 ASP.NET Core SignalR 中樞,與在 ASP.NET Core Web 應用程式中裝載的方式相同。 在 Startup.ConfigureServices 方法中,呼叫 services.AddSignalR 會將必要的服務新增至 ASP.NET Core 相依性插入 (DI) 層,以支援 SignalR。 在 Startup.Configure中,會呼叫 UseSignalR 方法來連線 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");
        });
    }
}

在上述範例中,類別 ClockHub 會實作 Hub<T> 類別來建立強型別中樞。 已在 Startup 類別中設定 ClockHub,以回應端點 /hubs/clock 的要求。

如需強型別中樞的詳細資訊,請參閱在適用於 SignalR 的 ASP.NET Core 中使用中樞

注意

這項功能不限於中樞<T> 類別。 繼承自中樞的任何類別 (例如 DynamicHub) 均適用。

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

強型別 ClockHub 所使用的介面是 IClock 介面。

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

從背景服務呼叫 SignalR 中樞

在啟動期間,將使用 AddHostedService 啟用 Worker 類別 BackgroundService

services.AddHostedService<Worker>();

由於在 Startup 階段也會啟用,因此 SignalR 每個中樞都會附加至 ASP.NET Core HTTP 要求管線中的個別端點,因此每個中樞都會以伺服器上的 IHubContext<T> 來表示。 使用 ASP.NET Core 的 DI 功能,裝載層所具現化的其他類別 (例如 BackgroundService 類別、MVC 控制器類別或 Razor 頁面模型) 可以透過在建構期間接受 IHubContext<ClockHub, IClock> 執行個體來取得伺服器端中樞的參考。

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

當背景服務中反覆呼叫 ExecuteAsync 方法時,伺服器目前的日期和時間會使用 ClockHub傳送至連線的用戶端。

使用背景服務回應 SignalR 事件

如同使用 SignalR 之 JavaScript 用戶端的單頁應用程式,或使用 ASP.NET Core SignalR .NET 用戶端的 .NET 傳統型應用程式一樣,BackgroundServiceIHostedService 實作也可用於連線至 SignalR 中樞並回應事件。

ClockHubClient 類別會同時實作 IClock 介面和 IHostedService 介面。 如此一來,就可以在 Startup 期間啟用,以持續執行,並從伺服器回應中樞事件。

public partial class ClockHubClient : IClock, IHostedService
{
}

初始化期間,ClockHubClient 會建立 HubConnection 的執行個體,並啟用 IClock.ShowTime 方法作為中樞 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;
}

IHostedService.StartAsync 實作中,會以非同步方式啟動 HubConnection

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

IHostedService.StopAsync 方法期間,HubConnection 會以非同步方式處置。

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

其他資源