如何在用户关闭 SignalR Blazor 中的浏览器时收到通知?
How to get notify when a user closes the browser in SignalR Blazor?
我想在用户离开时向组中所有连接的用户发送通知。我该怎么做?
正如您在我的代码中看到的那样,我已经覆盖了 OnDisconnectedAsync
方法,但它仅在我调用 HubConnection.DisposeAsync();
时起作用。但是如果我关闭浏览器或标签页,它什么都不做。
public override Task OnConnectedAsync()
{
Console.WriteLine("User Joined.");
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
Console.WriteLine("User Left.");
return base.OnDisconnectedAsync(exception);
}
有没有办法在浏览器关闭时收到通知?
Blazor Server allows code to define a circuit handler , which allows running code on changes to the state of a user's circuit. A circuit handler is implemented by deriving from CircuitHandler and registering the class in the app's service container.
public class TrackingCircuitHandler : CircuitHandler
{
private HashSet<Circuit> circuits = new HashSet<Circuit>();
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
circuits.Add(circuit);
return Task.CompletedTask;
}
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
circuits.Remove(circuit);
return Task.CompletedTask;
}
public int ConnectedCircuits => circuits.Count;
}
使用 DI 注册电路处理程序
services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();
您可以创建一个派生自 CircuitHandler 的服务class:
CircuitHandlerService.cs
using Microsoft.AspNetCore.Components.Server.Circuits;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
public class CircuitHandlerService : CircuitHandler
{
public ConcurrentDictionary<string, Circuit> Circuits { get; set; }
public event EventHandler CircuitsChanged;
protected virtual void OnCircuitsChanged()
=> CircuitsChanged?.Invoke(this, EventArgs.Empty);
public CircuitHandlerService()
{
Circuits = new ConcurrentDictionary<string, Circuit>();
}
public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuits[circuit.Id] = circuit;
OnCircuitsChanged();
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}
public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuit circuitRemoved;
Circuits.TryRemove(circuit.Id, out circuitRemoved);
OnCircuitsChanged();
return base.OnCircuitClosedAsync(circuit, cancellationToken);
}
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionDownAsync(circuit, cancellationToken);
}
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionUpAsync(circuit, cancellationToken);
}
}
将服务添加到 DI 容器:
services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
测试服务:
@page "/"
@using Microsoft.AspNetCore.Components.Server.Circuits
@inject CircuitHandler circuitHandler
@implements IDisposable
<h1>Hello, world!</h1>
Welcome to your new app.
<p>
Number of Circuits: @((circuitHandler as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits.Count)
<ul>
@foreach (var circuit in (circuitHandler as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits)
{
<li>@circuit.Key</li>
}
</ul>
</p>
@code {
protected override void OnInitialized()
{
// register event handler
(circuitHandler as CircuitHandlerService).CircuitsChanged += HandleCircuitsChanged;
}
public void Dispose()
{
// unregister the event handler when the component is destroyed
(circuitHandler as CircuitHandlerService).CircuitsChanged -= HandleCircuitsChanged;
}
public void HandleCircuitsChanged(object sender, EventArgs args)
{
// notify the UI that the state has changed
InvokeAsync(() => StateHasChanged());
}
}
我想在用户离开时向组中所有连接的用户发送通知。我该怎么做?
正如您在我的代码中看到的那样,我已经覆盖了 OnDisconnectedAsync
方法,但它仅在我调用 HubConnection.DisposeAsync();
时起作用。但是如果我关闭浏览器或标签页,它什么都不做。
public override Task OnConnectedAsync()
{
Console.WriteLine("User Joined.");
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
Console.WriteLine("User Left.");
return base.OnDisconnectedAsync(exception);
}
有没有办法在浏览器关闭时收到通知?
Blazor Server allows code to define a circuit handler , which allows running code on changes to the state of a user's circuit. A circuit handler is implemented by deriving from CircuitHandler and registering the class in the app's service container.
public class TrackingCircuitHandler : CircuitHandler
{
private HashSet<Circuit> circuits = new HashSet<Circuit>();
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
circuits.Add(circuit);
return Task.CompletedTask;
}
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
circuits.Remove(circuit);
return Task.CompletedTask;
}
public int ConnectedCircuits => circuits.Count;
}
使用 DI 注册电路处理程序
services.AddSingleton<CircuitHandler, TrackingCircuitHandler>();
您可以创建一个派生自 CircuitHandler 的服务class:
CircuitHandlerService.cs
using Microsoft.AspNetCore.Components.Server.Circuits;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
public class CircuitHandlerService : CircuitHandler
{
public ConcurrentDictionary<string, Circuit> Circuits { get; set; }
public event EventHandler CircuitsChanged;
protected virtual void OnCircuitsChanged()
=> CircuitsChanged?.Invoke(this, EventArgs.Empty);
public CircuitHandlerService()
{
Circuits = new ConcurrentDictionary<string, Circuit>();
}
public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuits[circuit.Id] = circuit;
OnCircuitsChanged();
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}
public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
Circuit circuitRemoved;
Circuits.TryRemove(circuit.Id, out circuitRemoved);
OnCircuitsChanged();
return base.OnCircuitClosedAsync(circuit, cancellationToken);
}
public override Task OnConnectionDownAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionDownAsync(circuit, cancellationToken);
}
public override Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
return base.OnConnectionUpAsync(circuit, cancellationToken);
}
}
将服务添加到 DI 容器:
services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
测试服务:
@page "/"
@using Microsoft.AspNetCore.Components.Server.Circuits
@inject CircuitHandler circuitHandler
@implements IDisposable
<h1>Hello, world!</h1>
Welcome to your new app.
<p>
Number of Circuits: @((circuitHandler as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits.Count)
<ul>
@foreach (var circuit in (circuitHandler as BlazorCircuitHandler.Services.CircuitHandlerService).Circuits)
{
<li>@circuit.Key</li>
}
</ul>
</p>
@code {
protected override void OnInitialized()
{
// register event handler
(circuitHandler as CircuitHandlerService).CircuitsChanged += HandleCircuitsChanged;
}
public void Dispose()
{
// unregister the event handler when the component is destroyed
(circuitHandler as CircuitHandlerService).CircuitsChanged -= HandleCircuitsChanged;
}
public void HandleCircuitsChanged(object sender, EventArgs args)
{
// notify the UI that the state has changed
InvokeAsync(() => StateHasChanged());
}
}