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

如何实现每两分钟执行一次操作的Timer定时器?

问题:Timer每两分钟执行一次操作,仅首次触发后续失效

我希望Timer每两分钟执行一次操作,使用Stopwatch和Timer组件实现,但目前仅在第一个两分钟后执行操作,后续周期均失效。以下是我尝试的两种代码逻辑及完整实现代码,寻求正确的改写方案:

尝试的两种逻辑

第一种逻辑

MainTimer.Text = stopwatch.Elapsed.ToString(@"hh\:mm\:ss");
double counter = stopwatch.Elapsed.TotalSeconds;
if ((int)counter == 120 )
{
    // do sth
    counter = 0;
}

第二种逻辑

MainTimer.Text = stopwatch.Elapsed.ToString(@"hh\:mm\:ss");
double counter = stopwatch.Elapsed.TotalSeconds;
if ((int)counter % 120 == 0 )
{
    // do sth
}

完整实现代码

Timer timer = new Timer(1000);
Stopwatch stopwatch = new Stopwatch();

public MainPage()
{
    InitializeComponent();
    MainFunctionTimer();
    DeviceDisplay.KeepScreenOn = true;
}
bool Value = false;
string Time = "00:00:00";

private void MainFunctionTimer()
{
    MainTimer.Text = Time;
    stopwatch = new Stopwatch();
    timer.Interval = 500;
    timer.Elapsed += OnTimerElapsed;
}

private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
    Application.Current.Dispatcher.BeginInvokeOnMainThread(() =>
    {
        MainTimer.Text = stopwatch.Elapsed.ToString(@"hh\:mm\:ss");
        double counter = stopwatch.Elapsed.TotalSeconds;
        
        if ((int)counter == 120 )
        {
            // do sth
            counter = 0;
        }
    });
}

private void Start_Stop_Butt_Clicked(object sender, EventArgs e)
{
    if (Value == false)
    {
        Value = true;
        stopwatch.Start();
        timer.Start();
    }
    else
    {
        Value = false;
        stopwatch.Stop();
        timer.Stop();
    }
}

private void Reset_Clicked(object sender, EventArgs e)
{
    stopwatch.Reset();
    MainTimer.Text = Time;
}

问题分析与解决方案

问题原因

  1. 第一种逻辑中,你重置的是局部变量counter,而非Stopwatch的计时,Stopwatch会继续累计时间,后续counter永远不会再等于120。
  2. 第二种逻辑会在0、120、240等秒数触发,但因为Timer的Interval是500ms,在120秒的瞬间会连续触发多次(比如TotalSeconds在120.0到120.5之间时,(int)counter始终是120),同时如果Stopwatch暂停后继续,可能出现判断逻辑混乱。

正确改写方案

维护一个上次执行操作的时间戳,每次Timer触发时计算当前Stopwatch的时间与上次执行时间的差值,达到120秒就执行操作并更新时间戳,既避免重复触发,也能保证每两分钟执行一次:

Timer timer = new Timer(1000);
Stopwatch stopwatch = new Stopwatch();
// 记录上次执行操作的时间(以秒为单位)
double lastExecuteTime = 0;

public MainPage()
{
    InitializeComponent();
    MainFunctionTimer();
    DeviceDisplay.KeepScreenOn = true;
}
bool Value = false;
string Time = "00:00:00";

private void MainFunctionTimer()
{
    MainTimer.Text = Time;
    stopwatch = new Stopwatch();
    timer.Interval = 500;
    timer.Elapsed += OnTimerElapsed;
}

private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
    Application.Current.Dispatcher.BeginInvokeOnMainThread(() =>
    {
        var elapsedSeconds = stopwatch.Elapsed.TotalSeconds;
        MainTimer.Text = stopwatch.Elapsed.ToString(@"hh\:mm\:ss");
        
        // 判断距离上次执行是否超过/等于120秒
        if (elapsedSeconds - lastExecuteTime >= 120)
        {
            // do sth - 这里写你的操作逻辑
            // 更新上次执行时间为当前时间
            lastExecuteTime = elapsedSeconds;
        }
    });
}

private void Start_Stop_Butt_Clicked(object sender, EventArgs e)
{
    if (Value == false)
    {
        Value = true;
        stopwatch.Start();
        timer.Start();
    }
    else
    {
        Value = false;
        stopwatch.Stop();
        timer.Stop();
    }
}

private void Reset_Clicked(object sender, EventArgs e)
{
    stopwatch.Reset();
    MainTimer.Text = Time;
    // 重置上次执行时间,避免恢复计时后立即触发操作
    lastExecuteTime = 0;
}

额外说明

  • 这种方式不依赖精确的秒数匹配,通过时间差判断避免了Timer间隔导致的重复触发或漏触发问题。
  • 重置Stopwatch时同时重置lastExecuteTime,确保下次启动计时时重新开始计算两分钟周期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:20:33