记录简单实现一个频率触发器

什么是频率触发器?

比如我们想记录在短时间内某个动作是否连续触发了满足条件的次数(比如双击),我遇到的一个使用场景是,命令内按esc不退出但是0.3s内连续按两次esc就退出。

实现

/// <summary>
/// 检测指定时间窗口内的连续触发次数
/// </summary>
/// <param name="times">触发所需的次数</param>
/// <param name="milliseconds">统计触发次数的时间窗口,单位为毫秒</param>
public sealed class FrequencyTrigger(int times, int milliseconds)
{
    /// <summary>
    /// 获取或设置触发所需的次数
    /// </summary>
    public int Times { get; set; } = times;

    /// <summary>
    /// 获取或设置统计触发次数的时间窗口,单位为毫秒
    /// </summary>
    public int Milliseconds { get; set; } = milliseconds;

    private readonly Queue<long> _queue = [];

    /// <summary>
    /// 记录一次命中并判断指定时间窗口内的命中次数是否达到触发次数
    /// </summary>
    /// <returns>达到触发次数时为 <c>true</c></returns>
    public bool Hit()
    {
        var now = Environment.TickCount;
        _queue.Enqueue(now);
        var cut = now - Milliseconds;
        while (_queue.Count > 0 && _queue.Peek() < cut)
        {
            _queue.Dequeue();
        }
        return _queue.Count >= Times;
    }

    /// <summary>
    /// 重置
    /// </summary>
    public void Reset()
    {
        _queue.Clear();
    }
}

使用方式

0.3秒内判断触发两次

var frequencyTrigger = new FrequencyTrigger(2,300);
while (true)
{
    if (someBool)
    {
        if (frequencyTrigger.Hit())
        {
            // do something
        }
    }