Detect client closing connection Blazor

扶醉桌前 提交于 2020-06-16 17:07:10

问题


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?


回答1:


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



回答2:


If it's an individual page that this is working on, have the page inherit OwningComponentBase (preferred) or implement IDisposable, then set the loop with an exit flag, or if it's a looping task set up a CancellationTokenSource and token on the task. Then when the user leaves the page and it tears down, override the Dispose Method and either flip the exit flag or set the token source to 'Cancelled' and your loop should exit.

If you need to go deeper, This Link to the documents discusses server side circuits which may help. For client side, the dispose methods should work if running in a browser, but if you have a server side process kicked off through an API you would need to let that run it's course as the client side of a session would be in a faulted state, and if you use JWT the token will have it's own expiration and the server wouldn't be involved. I'd recommend building in timeouts where needed as a safeguard.



来源:https://stackoverflow.com/questions/61345537/detect-client-closing-connection-blazor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!