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

如何使用Timer实现方法的定时循环调用(指定总时长)

实现带总时长限制的蜂鸣器状态循环处理器

原代码

internal class BuzzerStateTimedProcessor
{
    private Timer _timer;
    private bool _executed = true;

    public BuzzerStateTimedProcessor()
    {
        _timer = new(OnTimer);
    }

    private void DurationOn()
        => Console.WriteLine("duration on");

    private void DurationOff()
        => Console.WriteLine("duration off");

    private TimeSpan _durationOff;
    private TimeSpan _durationOn;
    private TimeSpan _cycles;
    private TimeSpan _repeatCount;
    public void DurationCycle(
        TimeSpan? duration,
        TimeSpan durationOn,
        TimeSpan durationOff)
    {
        _durationOff = durationOff;
        _durationOn = durationOn;

        var permanentOperation = !duration.HasValue;

        if (permanentOperation)
        {
            _timer.Change(TimeSpan.Zero, durationOn);
        }
        else
        {
            _cycles = TimeSpan.Zero;
            _repeatCount = duration.Value;

            /// some logic
        }
    }

    private void OnTimer(object state)
    {
        if (_executed)
            DurationOn();
        else
            DurationOff();

        _executed = !_executed;
    }
}

当前可用功能

调用DurationCycle时传入null作为总时长参数,可实现永久循环执行DurationOn()和DurationOff():

var test = new BuzzerStateTimedProcessor();
test.DurationCycle(null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));

执行效果:先执行DurationOn(),等待2秒后执行DurationOff(),再等待2秒,以此循环往复。

需求说明

需要补充逻辑,当传入总时长(比如10秒)时,在指定时长内循环执行上述方法,时间到后自动停止循环。调用示例如下:

var test = new BuzzerStateTimedProcessor();
test.DurationCycle(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2));

修改后的完整代码实现

通过添加时间记录、动态调整定时器间隔的方式实现时长限制:

internal class BuzzerStateTimedProcessor
{
    private Timer _timer;
    private bool _executed = true;
    // 记录循环启动时间
    private DateTime? _cycleStartTime;
    // 存储总时长限制
    private TimeSpan? _totalDuration;

    public BuzzerStateTimedProcessor()
    {
        _timer = new(OnTimer);
    }

    private void DurationOn()
        => Console.WriteLine("duration on");

    private void DurationOff()
        => Console.WriteLine("duration off");

    private TimeSpan _durationOff;
    private TimeSpan _durationOn;
    
    public void DurationCycle(
        TimeSpan? duration,
        TimeSpan durationOn,
        TimeSpan durationOff)
    {
        _durationOff = durationOff;
        _durationOn = durationOn;
        _totalDuration = duration;

        var permanentOperation = !duration.HasValue;

        if (permanentOperation)
        {
            // 永久循环:首次立即执行,之后交替使用On/Off时长作为间隔
            _timer.Change(TimeSpan.Zero, _durationOn);
        }
        else
        {
            // 带时长限制的循环:初始化启动时间,首次立即执行
            _cycleStartTime = DateTime.Now;
            _timer.Change(TimeSpan.Zero, Timeout.InfiniteTimeSpan);
        }
    }

    private void OnTimer(object state)
    {
        // 执行当前状态对应的方法
        if (_executed)
            DurationOn();
        else
            DurationOff();

        // 检查是否需要停止循环
        if (_totalDuration.HasValue && _cycleStartTime.HasValue)
        {
            var elapsedTime = DateTime.Now - _cycleStartTime.Value;
            if (elapsedTime >= _totalDuration.Value)
            {
                _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
                return;
            }
        }

        // 切换状态,计算下一次触发的间隔
        _executed = !_executed;
        var nextInterval = _executed ? _durationOn : _durationOff;

        // 避免下一次间隔超出剩余时长
        if (_totalDuration.HasValue && _cycleStartTime.HasValue)
        {
            var elapsedTime = DateTime.Now - _cycleStartTime.Value;
            var remainingTime = _totalDuration.Value - elapsedTime;
            if (nextInterval > remainingTime)
            {
                _timer.Change(remainingTime, Timeout.InfiniteTimeSpan);
                return;
            }
        }

        // 设置下一次触发时间
        _timer.Change(nextInterval, Timeout.InfiniteTimeSpan);
    }
}

关键修改点

  1. 新增_cycleStartTime和_totalDuration字段,分别记录循环启动时间和总时长限制
  2. 带时长限制的循环初始化时,将定时器设置为单次触发,后续在OnTimer方法中动态调整下一次触发间隔
  3. 每次触发后计算已消耗时长,若超出总限制则停止定时器;若未超出,则检查下一次间隔是否会超过剩余时长,避免执行超出总时长的操作
  4. 统一永久循环和限时循环的间隔逻辑,确保两种模式下On/Off的间隔都符合设置值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:50:38