定时器有时不触发
Timer sometimes not triggering
---更新---
我现在可以说,每次定时器无法触发时,我都会在调试输出中收到以下错误消息。当我收到错误消息时,定时器有 100% 的时间会失败。
Failed to load resource: net::ERR_HTTP2_PROTOCOL_ERROR [https://localhost:44371/_framework/blazor.server.js] Exception thrown: 'Microsoft.AspNetCore.Connections.ConnectionResetException' in Microsoft.AspNetCore.Server.IIS.dll
然而,实时站点(在 Windows 服务器上)有时也无法触发计时器,所以我认为这不仅仅是 VS 调试问题。
---/更新---
我的门厅页面上有一个持续 3 秒的动画 svg。我想在 3 秒后显示其他控件:登录按钮、“游览”等,因此我添加了一个在 OnAfterRender 中启动的计时器(也尝试过 OnAfterRenderAsync)。
问题是大约有 1/3 的时间(随机出现的概率为 1/20 或更多),计时器的处理程序不会触发,并且不会显示控件。我假设这是某种线程竞争条件,但我真的不明白可以做些什么。
我试过:
- 使用
async
生命周期事件和处理程序
await ()=>
表达式等各种组合
(注意——我知道我可以使用动画 CSS 来做到这一点,但我现在限制测试计时器的使用)
这是一些简化的代码:
<MyCoolAnimation / >
@if (ShowControls)
{
// various controls
}
@code {
bool ShowControls;
protected override void OnAfterRender(bool firstRender)
{
if (!firstRender)
{
Timer = new Timer(3000);
Timer.Elapsed += CountDownTimer;
Timer.Start();
}
}
private async void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e)
{
Timer.Stop();
Timer.Dispose();
ShowControls = true;
await InvokeAsync(StateHasChanged);
}
}
if (!firstRender)
很奇怪 - 你会有很多计时器 运行.
这有点提供了答案,Timer = new Timer(3000);
和 Timer.Dispose();
部分有竞争条件(至少在 Blazor Server 上)。
- 确保您的页面上只有 1 个计时器实例
- 在 OnInitialized() 中创建并启动它
- 使用
@implements IDisposable
清理
是一些示例代码。
在这种情况下,我会避免整个计时器问题。
您可以在没有计时器、处置模式或 InvokeAsync 的情况下执行此操作。保持简单:
<MyCoolAnimation / >
@if (ShowControls)
{
// various controls
}
@code {
bool ShowControls;
protected override async Task OnInitializedAsync()
{
ShowControls = false;
await Task.Delay(3_000);
ShowControls = true;
}
}
我对调用 Timer.Dispose()
inside elapsed 处理程序有疑问。但是找不到关于它的权威声明。
(v3)
最后更新:
我受够了。感谢您的帮助,伙计们!现在,Henk 的以下建议有效。我进行了 Windows 更新,我认为这是问题所在——但我仍然无法让 Timer 版本正常工作。我谨慎乐观地认为问题出在生命周期,而不是一般的定时器。
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!ShowControls)
{
await Task.Delay(3000);
ShowControls = true;
StateHasChanged();
}
}
在我看来,在 Blazor 生命周期内实例化 Timer 对象甚至可能过于挑剔而无法使其可靠地工作。
我唯一的希望是我使用 Timer 做的其他事情(比如通过服务弹出排队的消息)也不会在 5% 的时间内中断。
---更新---
我现在可以说,每次定时器无法触发时,我都会在调试输出中收到以下错误消息。当我收到错误消息时,定时器有 100% 的时间会失败。
Failed to load resource: net::ERR_HTTP2_PROTOCOL_ERROR [https://localhost:44371/_framework/blazor.server.js] Exception thrown: 'Microsoft.AspNetCore.Connections.ConnectionResetException' in Microsoft.AspNetCore.Server.IIS.dll
然而,实时站点(在 Windows 服务器上)有时也无法触发计时器,所以我认为这不仅仅是 VS 调试问题。
---/更新---
我的门厅页面上有一个持续 3 秒的动画 svg。我想在 3 秒后显示其他控件:登录按钮、“游览”等,因此我添加了一个在 OnAfterRender 中启动的计时器(也尝试过 OnAfterRenderAsync)。
问题是大约有 1/3 的时间(随机出现的概率为 1/20 或更多),计时器的处理程序不会触发,并且不会显示控件。我假设这是某种线程竞争条件,但我真的不明白可以做些什么。
我试过:
- 使用
async
生命周期事件和处理程序 await ()=>
表达式等各种组合
(注意——我知道我可以使用动画 CSS 来做到这一点,但我现在限制测试计时器的使用)
这是一些简化的代码:
<MyCoolAnimation / >
@if (ShowControls)
{
// various controls
}
@code {
bool ShowControls;
protected override void OnAfterRender(bool firstRender)
{
if (!firstRender)
{
Timer = new Timer(3000);
Timer.Elapsed += CountDownTimer;
Timer.Start();
}
}
private async void CountDownTimer(Object source, System.Timers.ElapsedEventArgs e)
{
Timer.Stop();
Timer.Dispose();
ShowControls = true;
await InvokeAsync(StateHasChanged);
}
}
if (!firstRender)
很奇怪 - 你会有很多计时器 运行.
这有点提供了答案,Timer = new Timer(3000);
和 Timer.Dispose();
部分有竞争条件(至少在 Blazor Server 上)。
- 确保您的页面上只有 1 个计时器实例
- 在 OnInitialized() 中创建并启动它
- 使用
@implements IDisposable
清理
在这种情况下,我会避免整个计时器问题。
您可以在没有计时器、处置模式或 InvokeAsync 的情况下执行此操作。保持简单:
<MyCoolAnimation / >
@if (ShowControls)
{
// various controls
}
@code {
bool ShowControls;
protected override async Task OnInitializedAsync()
{
ShowControls = false;
await Task.Delay(3_000);
ShowControls = true;
}
}
我对调用 Timer.Dispose()
inside elapsed 处理程序有疑问。但是找不到关于它的权威声明。
(v3)
最后更新:
我受够了。感谢您的帮助,伙计们!现在,Henk 的以下建议有效。我进行了 Windows 更新,我认为这是问题所在——但我仍然无法让 Timer 版本正常工作。我谨慎乐观地认为问题出在生命周期,而不是一般的定时器。
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!ShowControls)
{
await Task.Delay(3000);
ShowControls = true;
StateHasChanged();
}
}
在我看来,在 Blazor 生命周期内实例化 Timer 对象甚至可能过于挑剔而无法使其可靠地工作。
我唯一的希望是我使用 Timer 做的其他事情(比如通过服务弹出排队的消息)也不会在 5% 的时间内中断。