定时器有时不触发

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 或更多),计时器的处理程序不会触发,并且不会显示控件。我假设这是某种线程竞争条件,但我真的不明白可以做些什么。

我试过:

(注意——我知道我可以使用动画 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% 的时间内中断。