任何服务器端 blazor 组件都不会调用 Dispose

问题描述 投票:0回答:1

我们有一个 .Net Core 6 应用程序,我们正在使用 Blazor 服务器组件慢慢将 UI 功能从 JS 过渡到 Blazor。在大多数情况下,一切都工作正常,但是我们引入了几个组件,它们具有计时器,用于刷新可以在用户操作之外更改的项目状态,例如网络状态。一切工作正常,除了当离开组件所在的页面时,组件的 Dispose 方法永远不会被调用,这会使计时器继续运行。

以下是从 cshtml 页面调用该组件的方式:

<component type="typeof(APStatus)" render-mode="Server" /\>

这是 OnInitializedAsync 中的计时器定义。

_timer = new System.Timers.Timer(10000);
_timer.Elapsed += CountDownTimer;
_timer.Start();
_timer.Enabled = true;

这是 CountDownTimer 回调:

public async void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e)
{
    if (_internalCounter > 0)
    {
        _internalCounter -= 1;
    }
    else
    {
        _timer.Enabled = false;
        _timer.Stop();
    }
    await InvokeAsync(async () =>
    {
        if (NetInfo != null)
        {
            await GetApStatus();
            
        }
    });
}

这是处置方法:

public void Dispose()
{
    System.Diagnostics.Debug.WriteLine("Disposing Happened");
    _timer.Enabled = false;
    _timer.Stop();
    _timer.Dispose();
    _timer = null;   
}

我添加了一个 CircuitHandler,同样的问题,我收到 OnCircuitOpenAsync 事件,但闭路从未触发。

这是一些 CircuitHandler 代码:

public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken)
{
    Console.WriteLine("OnCircuitClosedAsync");
    Circuits.TryRemove(circuit.Id, out var circuitRemoved);
    OnCircuitsChanged();
    return base.OnCircuitClosedAsync(circuit, cancellationToken);
}

我几乎尝试了我能想到的所有方法,通过了 Program.cs,调用组件的各种方式,从 chrome 开发工具的角度来看,一切似乎都工作正常,日志中没有奇怪的错误消息。

我打开了 Blazor 日志记录,但没有显示任何内容。

我几乎搜索了所有能找到的论坛,寻找有类似问题的人,但找不到任何关于为什么会发生这种情况的信息。

我现场还有其他 blazor 组件,一切正常。我已将 Dispose 添加到所有这些中,并且没有一个被解雇。

我已更新到最新的 .net core 6 软件包,但没有成功。

我开始了一个新项目,并在 blazor 组件中实现了计时器的 Microsoft 代码,它工作正常,在离开页面时按预期调用 Dispose。

当我将该组件复制到我们的项目中时,一切正常,但是当我离开打开该组件的页面时,什么也没有,Dispose 永远不会被调用。

这是计数器示例:

@page "/counter"
@using System.Timers
@using System.Diagnostics
@implements IDisposable
<PageTitle\>Counter\</PageTitle\>

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<p>Current count: @timerCount</p>

<button class="btn btn-primary" @onclick="IncrementCount"\>Click me\</button\>

@code {
private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
    private int timerCount = 0;
    private Timer timer = new(1000);
    
    protected override void OnInitialized()
    {
        timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
        timer.Start();
    }
    
    private void OnTimerCallback()
    {
        _ = InvokeAsync(() =>
        {
            timerCount++;
            StateHasChanged();
        });
    }
    
    public void Dispose()
    {
        Debug.WriteLine("Disposing");
        timer.Dispose();
    }

}

更新1

经过大量研究和调整主要与电路相关的内容后,我在 Program.cs 中使用它设置了 DisconnectedCircuitRetentionPeriod

builder.Services.AddServerSideBlazor().AddCircuitOptions(options =>
{
    options.DetailedErrors = true;
    options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromSeconds(10);
});

处理时间从大约 3.5 分钟缩短到 10 秒或更短。仍在努力理解为什么这是必要的,但似乎是进步。

更新2

测试此组件以及网站上的所有其他 blazor 组件后,这似乎已经解决了问题,并且似乎没有引起任何其他问题。做了更多研究后

我也发现了这个问题和答案,似乎表明它可以解决此类处理组件的问题。

我不确定为什么在某些情况下尝试处理时这种情况并不常见。我希望这对其他人有帮助。

c# blazor blazor-server-side
1个回答
0
投票

解决方案是将其添加到 Program.cs 中

.AddCircuitOptions(options =>
                {
                    options.DetailedErrors = true;
                    options.DisconnectedCircuitRetentionPeriod = TimeSpan.FromSeconds(0);
                    options.DisconnectedCircuitMaxRetained = 0;
                });

看起来保留期默认为 3 分钟,这与最终调用 Dispose 所需的时间一致。

正如上次更新中提到的,我发现了这个问题和答案,这似乎表明它可以解决此类组件处置问题。

© www.soinside.com 2019 - 2024. All rights reserved.