Search code examples
blazorlifecycle

Detect client closing connection Blazor


I have a loop that I have got running the whole time the client is on the page but I got no way to close the loop so that always remains running even when the user already disconnected. Is there a lifecycle method that runs when the user closes the connection? or is there a different way?


Solution

  • I'm not sure just implementing the IDisposable Interface can help you here, but implementing the Blazor Server circuit handler may. I vaguely recall that a similar question to yours was asked in stackoverflow... the OP tried to implement the IDisposable Interface, but to no avail. I've answered once or twice that question and a follow up one...I'm posting the code from my answer, and I hope this helps you...

    CircuitHandlerService.cs

    using Microsoft.AspNetCore.Components.Server.Circuits;
    using System;
    using System.Collections.Concurrent;
    using System.Threading;
    using System.Threading.Tasks;
    
    
    namespace BlazorCircuitHandler.Services
    {
      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)
        {
            Console.WriteLine("OnCircuitClosedAsync");
            Circuit circuitRemoved;
            Circuits.TryRemove(circuit.Id, out circuitRemoved);
            OnCircuitsChanged();
            return base.OnCircuitClosedAsync(circuit, cancellationToken);
        }
    
        public override Task OnConnectionDownAsync(Circuit circuit, 
                        CancellationToken cancellationToken)
        {
            Console.WriteLine("OnConnectionDownAsync");
            return base.OnConnectionDownAsync(circuit, cancellationToken);
        }
    
        public override Task OnConnectionUpAsync(Circuit circuit, 
            CancellationToken cancellationToken)
        {
            return base.OnConnectionUpAsync(circuit, cancellationToken);
        }
    
      }
     }
    

    Usage

    @page "/"
    
    @using Microsoft.AspNetCore.Components.Server.Circuits
    @using BlazorCircuitHandler.Services
    
    @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());
     }
    }
    

    Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
       // ........ .....
       services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
    }