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
调用。
我有以下问题:
我有一个前端,其中某些值由后端设置。值保存在列表中,这些列表元素应该显示在前端。
这在首次加载、手动刷新页面等时有效...但在使用 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
调用。