如何在 blazor 服务器端渲染页面时停止 IDisposable 调用? [英] How can I stop IDisposable invokes while render the page in blazor server-side?

查看:26
本文介绍了如何在 blazor 服务器端渲染页面时停止 IDisposable 调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码:

@page "/"
@using Microsoft.AspNetCore.Components.Server.Circuits
@inject CircuitHandler circuitHandler
@implements IDisposable

<h1>Hello, world!</h1>

Welcome to your new app.

@code{
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            Console.WriteLine("123");//do something
        }
    }
    #region//circuitHandler
    protected override void OnInitialized()
    {
        // Subscribe to the event handler
        (circuitHandler as CircuitHandlerService).CircuitsChanged +=
             HandleCircuitsChanged;

    }


    public void HandleCircuitsChanged(object sender, EventArgs args)
    {
        Console.WriteLine("123");//do something
    }
    public void Dispose()
    {
        (circuitHandler as CircuitHandlerService).CircuitsChanged -=
          HandleCircuitsChanged;

    }
    #endregion
}


using Microsoft.AspNetCore.Components.Server.Circuits;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace BlazorApp2
{
    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);
        }
    }
}



我需要 CircuitHandler 来了解页面是否关闭.

现在我遇到了一个奇怪的问题.当页面被加载时,即使页面没有关闭,IDisposable 总是会被调用.

更重要的是,OnAfterRenderAsync 中有几个代码.当IDisposable调用时,OnAfterRenderAsync中没有运行完的代码会突然断掉,没有任何错误.

有人告诉我设置



I need the CircuitHandler to get to know whether the page is closed.

Now I met a strange problem. When the page is loaded, the IDisposable always invoke even the page is not closed.

What's more, there are several codes in OnAfterRenderAsync. When the IDisposable invokes, the codes in OnAfterRenderAsync which not runs finished will suddenly break without any error.

Someone told me to set the

@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))

_Host.cshtml

@(await Html.RenderComponentAsync<App>(RenderMode.Server))

可以解决这个问题.

我试过了,问题依旧.

我该如何解决这个问题?谢谢.

can solve this.

I tried, but the problem still here.

How can I solve this? Thank you.

推荐答案

下面的代码片段与您的完全一样,对我来说非常好.Dispose 方法仅在电路关闭时调用.我会在下面发布我使用的完整代码,复制并运行它,然后我会尝试帮助您解决其他问题.

the code snippet below is exactly like yours, and it works for me perfectly fine. The Dispose method is called only when a Circuit is closed. I'll post below the entire code I use, copy and run it, then I'll try to help with other issues you have.

<app>
        @(await Html.RenderComponentAsync<App>(RenderMode.Server))
 </app>

注意:我在这里发布整个文件的内容.你必须用你的命名空间来调整我的应用程序的命名空间.

Note: I'm posting here entire files' content. You'll have to adjust the namespaces of my app with yours.

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)
    {

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

 }
}

Index.razor 的代码

@page "/"

@using Microsoft.AspNetCore.Components.Server.Circuits
@using BlazorCircuitHandler.Services

@inject CircuitHandler circuitHandler
@implements IDisposable


<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()
{
    (circuitHandler as CircuitHandlerService).CircuitsChanged += 
                   HandleCircuitsChanged;

}

public void Dispose()
{

    (circuitHandler as CircuitHandlerService).CircuitsChanged -= 
              HandleCircuitsChanged;

}

public void HandleCircuitsChanged(object sender, EventArgs args)
{
    InvokeAsync(() => StateHasChanged());
}
}

还有创业班

public void ConfigureServices(IServiceCollection services)
    {
        // Removed for brevity....

        services.AddSingleton<CircuitHandler>(new CircuitHandlerService());
    }

当然还有_Host.cshtml

<app>
        @(await Html.RenderComponentAsync<App>(RenderMode.Server))
</app>

请不要漏报...

这篇关于如何在 blazor 服务器端渲染页面时停止 IDisposable 调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆