You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

意外递归Sub问题:PopulateStatusBar重复执行求助

问题修复方案

1. 修复定时器配置错误

你当前PerformLoadMe方法里创建的System.Timers.Timer未设置触发间隔(Interval),默认值为0,结合AutoReset=True会导致定时器疯狂触发Elapsed事件,这是PopulateStatusBar重复执行的核心原因之一。

修改代码如下:

Private Sub PerformLoadMe()
    ' 设置定时器间隔为1秒(1000毫秒),可根据需求调整
    Dim tmr As New System.Timers.Timer With {.Interval = 1000, .AutoReset = True}
    AddHandler tmr.Elapsed, AddressOf PopulateStatusBar
    tmr.Enabled = True ' 最后启用定时器
    PopulateStatusBar() ' 初始化调用一次
End Sub

2. 避免属性赋值触发递归

如果AtlanticLabel是实现INotifyPropertyChanged的绑定属性,需确保属性赋值不会间接触发PopulateStatusBar重复调用。同时改用局部变量统一计算基准时间,避免全局变量引发的意外逻辑:

Private Sub PopulateStatusBar()
    ' 一次性获取UTC时间,作为所有时区计算的基准
    Dim utcNow As Date = Date.UtcNow
    
    ' 大西洋时区时间计算
    Dim atlanticZone As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Atlantic Standard Time")
    Dim atlanticLocal As Date = TimeZoneInfo.ConvertTimeFromUtc(utcNow, atlanticZone)
    AtlanticLabel = $" Atlantic {atlanticLocal.ToString("ddd HH:mm")} "
    
    ' 其他时区计算同理,全部基于同一个utcNow值
    ' ...
End Sub

3. 处理定时器的线程安全问题

System.Timers.Timer的Elapsed事件在ThreadPool线程触发,直接更新WPF UI会引发线程异常,需切换到UI线程执行:

' 适配定时器Elapsed事件的重载方法
Private Sub PopulateStatusBar(sender As Object, e As ElapsedEventArgs)
    PopulateStatusBar()
End Sub

Private Sub PopulateStatusBar()
    ' 检查是否需要切换到UI线程
    If Application.Current.Dispatcher.CheckAccess() = False Then
        Application.Current.Dispatcher.Invoke(AddressOf PopulateStatusBar)
        Return
    End If
    
    Dim utcNow As Date = Date.UtcNow
    ' 后续时间计算与UI赋值逻辑同上
    ' ...
End Sub

额外检查项

  • 排查是否有其他事件(如UI的Loaded、属性PropertyChanged)重复绑定了PopulateStatusBar
  • 确认RelayCommand的CanExecute逻辑不会导致命令被重复触发

内容的提问来源于stack exchange,提问作者SezMe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:55:13