检测客户端关闭连接Blazor

检测客户端关闭连接Blazor,blazor,lifecycle,Blazor,Lifecycle,我有一个循环,客户端在页面上的整个时间都在运行,但是我没有办法关闭循环,因此即使用户已经断开连接,循环也始终保持运行。是否存在在用户关闭连接时运行的生命周期方法?或者有不同的方法吗?如果这是一个单独的页面,则让该页面继承OwningComponentBase(首选)或实现IDisposable,然后使用退出标志设置循环,或者如果是循环任务,则在任务上设置取消令牌源和令牌。然后,当用户离开页面并将其撕下时,覆盖Dispose方法,翻转退出标志或将令牌源设置为“已取消”,您的循环应退出 如果您需要更

我有一个循环,客户端在页面上的整个时间都在运行,但是我没有办法关闭循环,因此即使用户已经断开连接,循环也始终保持运行。是否存在在用户关闭连接时运行的生命周期方法?或者有不同的方法吗?

如果这是一个单独的页面,则让该页面继承
OwningComponentBase
(首选)或实现
IDisposable
,然后使用退出标志设置循环,或者如果是循环任务,则在任务上设置
取消令牌源
和令牌。然后,当用户离开页面并将其撕下时,覆盖
Dispose
方法,翻转退出标志或将令牌源设置为“已取消”,您的循环应退出


如果您需要更深入地了解,请参阅文档中讨论的服务器端电路,这可能会有所帮助。对于客户端,如果在浏览器中运行,dispose方法应该可以工作,但是如果通过API启动了服务器端进程,则需要让该进程运行,因为会话的客户端将处于故障状态,并且如果使用JWT,令牌将有其自身的过期时间,服务器将不参与。我建议在需要的地方设置超时作为保护措施

如果这是一个单独的页面,则让该页面继承
OwningComponentBase
(首选)或实现
IDisposable
,然后使用退出标志设置循环,或者如果是循环任务,则在任务上设置
取消令牌源
和令牌。然后,当用户离开页面并将其撕下时,覆盖
Dispose
方法,翻转退出标志或将令牌源设置为“已取消”,您的循环应退出


如果您需要更深入地了解,请参阅文档中讨论的服务器端电路,这可能会有所帮助。对于客户端,如果在浏览器中运行,dispose方法应该可以工作,但是如果通过API启动了服务器端进程,则需要让该进程运行,因为会话的客户端将处于故障状态,并且如果使用JWT,令牌将有其自身的过期时间,服务器将不参与。我建议在需要的地方设置超时作为保护措施

我不确定仅仅实现IDisposable接口是否能在这方面帮助您,但是实现may。我隐约记得在stackoverflow中有人问过一个与你类似的问题。。。OP试图实现IDisposable接口,但没有成功。我已经回答了一两次这个问题,还有一个后续问题…我正在发布我的答案中的代码,我希望这能帮助你

CircuitHandlerService.cs
使用Microsoft.AspNetCore.Components.Server.Circuits;
使用制度;
使用System.Collections.Concurrent;
使用系统线程;
使用System.Threading.Tasks;
命名空间blazorcuithisandler.Services
{
公共类CircuitHandler服务:CircuitHandler
{
公共ConcurrentDictionary电路{get;set;}
公共事件处理程序发生故障;
受保护的虚拟void OnCircuitsChanged()
=>CircuitsChanged?.Invoke(这个,EventArgs.Empty);
公共电路HandlerService()
{
电路=新的ConcurrentDictionary();
}
CircuitOpenedAsync上的公共覆盖任务(电路,
取消令牌(取消令牌)
{
电路[circuit.Id]=电路;
OnCircuitsChanged();
返回base.OnCircuitOpenedAsync(电路,取消令牌);
}
CircuitClosedAsync上的公共覆盖任务(电路,
取消令牌(取消令牌)
{
Console.WriteLine(“OnCircuitClosedAsync”);
拆除电路;
Circuits.TryRemove(circuit.Id,out-circuit已移除);
OnCircuitsChanged();
返回base.OnCircuitClosedAsync(电路,取消令牌);
}
公共覆盖任务OnConnectionDownAsync(电路,
取消令牌(取消令牌)
{
WriteLine(“OnConnectionDownAsync”);
返回base.OnConnectionDownAsync(电路,取消令牌);
}
公共覆盖任务OnConnectionUpAsync(电路,
取消令牌(取消令牌)
{
返回base.OnConnectionUpAsync(电路,取消令牌);
}
}
}
用法
@page/“
@使用Microsoft.AspNetCore.Components.Server.Circuits
@使用BlazorCircuitHandler.Services
@注入电路处理程序电路处理程序
@实现IDisposable
你好,世界!
欢迎使用您的新应用程序。

电路数:@((电路处理器为
BlazorCircuithHandler.Services.CircuitHandlerService.Circuits.Count)
    @foreach(var)电路输入(circuitHandler as BlazorCircuithHandler.Services.CircuitHandler.Service).Circuits) {
  • @电路,钥匙
  • }

@代码{ 受保护的覆盖无效OnInitialized() { //寄存器事件处理程序 (circuitHandler作为CircuitHandlerService)。CircuitsChanged+= 手电路改变; } 公共空间处置() { //在组件销毁时注销事件处理程序 (circuitHandler作为CircuitHandlerService)。CircuitsChanged-= 手电路改变; } public void HandleCircuitsChanged(对象发送方、事件args args) { //通知UI状态已更改 InvokeAsync(()=>StateHasChanged()); } }
Startup.cs
public void配置服务(IServiceCollection服务)
{
// ........ .....
AddSingleton(新的CircuitHandlerService());
}

我不确定仅仅实现IDisposable接口是否能在这方面帮助您,但是实现may。我隐约记得在stackoverflow中有人问过一个与你类似的问题。。。OP试图实现IDisposable接口,但没有成功。那个问题我已经回答过一两次了
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);
    }

  }
 }
@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());
 }
}
public void ConfigureServices(IServiceCollection services)
{
   // ........ .....
   services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
}