Blazor 服务器端 UI 更新不起作用或仅部分起作用

Blazor-Server side UI Updating does not work or only partially

我有以下问题:

我有一个前端,其中某些值由后端设置。值保存在列表中,这些列表元素应该显示在前端。

这在首次加载、手动刷新页面等时有效...但在使用 StateHasChanged() 或 ShouldRender() 时无效

在搜索时我发现了这篇文章:

所以我加了定时器,定时器确实会刷新,但只有30秒左右,之后就不会再刷新了。

 <ul>
        @Time
 </ul>
System.Threading.Timer timer;
private string Time { get; set; }
protected override async Task OnInitializedAsync()
{
    _servers = DataCollection.srv;
    var timer = new System.Threading.Timer((_) =>
    {
        Time = DateTime.Now.ToString();
        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }, null, 0, 1000);
    base.OnInitialized();```

当计时器刷新时,所有其他元素也将被刷新。但是刷新计时器会随机停止,有时会在 60 秒后停止,有时会在 2 秒后停止。单击一个按钮(默认情况下会触发刷新)或任何其他操作都不会再次启动它。

我的问题是:为什么它只在随机的时间内有效?

感谢您的宝贵时间,如果这可能是微不足道的,我们深表歉意

<ul>
        @Time
        <button onclick="@Collect">Collect</button>
 </ul>

@code {
    System.Threading.Timer timer;
    private string Time { get; set; }
    protected override async Task OnInitializedAsync()
    {       
        var timer = new System.Threading.Timer((_) =>
        {
            Time = DateTime.Now.ToString();
            InvokeAsync(() =>
            {
                StateHasChanged();
            });
        }, null, 0, 1000);
        base.OnInitialized();
    }

    void Collect()
    {
        GC.Collect();            
    }
 }

https://try.mudblazor.com/snippet 上尝试上面的代码。由于您将 Timer 分配给方法范围中的局部变量,因此它最终会被垃圾收集并且您的计时器将不再触发。您可以使用上面的示例进行模拟,其中我引入了一个按钮来显式触发垃圾收集。 更改示例以分配给计时器变量而不是本地 var 计时器变量,并尝试再次触发垃圾收集,这次计时器不会停止。

这是我根据您的代码生成的测试页。它使用 Task.Delay 来模拟你的 _servers = DataCollection.srv;。它不会在 30-60 秒后冻结。

这表明 _servers = DataCollection.srv; 中存在问题。更改代码中 await Task./Delay(100) 的这一行并验证问题出在哪里。

@page "/"
<PageTitle>Index</PageTitle>

<div class="p-2">
    @this.Time
</div>

@code {

    System.Threading.Timer? timer;

    private string Time { get; set; } = string.Empty;

    protected override async Task OnInitializedAsync()
    {
        // emulate a data get
        await Task.Delay(100);
        var timer = new System.Threading.Timer((_) =>
        {
            Time = DateTime.Now.ToString();
            InvokeAsync(() =>
            {
                StateHasChanged();
            });
        }, null, 0, 1000);
        await base.OnInitializedAsync();
    }
}

还有你为什么要从 OnInitializedAsync() 打电话给 base.OnInitialized();

已经 运行: OnInitialized()OnInitializedAsync() 之前被 ComponentBase 调用。