每分钟计时器一次

时间:2016-05-07 19:44:10

标签: c# multithreading timer

我不能让计时器在每分钟,1:00,1:01,1:02等处每分钟发射一次。相反,当计时器每次迭代执行漂移几秒钟时

   internal void StartTimer()
    {
        DateTime nowEastern = CalendarEntity.Calendar.GetEasternTime();

        int secondsInterval = 5;

        double additionalSeconds = secondsInterval - nowEastern.TimeOfDay.TotalSeconds % secondsInterval;
        if (additionalSeconds == 0)
        {
            additionalSeconds = 1;
        }
        var nearestOnOneMinutes = new DateTime(
            nowEastern.Year,
            nowEastern.Month,
            nowEastern.Day,
            nowEastern.Hour,
            nowEastern.Minute,
            nowEastern.Second
        ).AddSeconds(additionalSeconds);

        TimeSpan timeToStart = nearestOnOneMinutes.Subtract(nowEastern);
        TimeSpan tolerance = TimeSpan.FromSeconds(1);
        if (timeToStart < tolerance)
        {
            timeToStart = TimeSpan.Zero;
        }

        timer_onem = new System.Threading.Timer(OnTimedEvent, null,
                                    (int)timeToStart.TotalMilliseconds, Timeout.Infinite);
    }

    private static void OnTimedEvent(object o)
    {
        var minute = DateTime.Now.Minute;
        var second = DateTime.Now.Second;
        if (minute != lastMinute && second % 60 < 2)
        {
            lastMinute = minute;
            CodeToExecute();
        }
    }

    static void CodeToExecute()
    {
        double tms = 60000;

        // code here
        int wait = 60 - System.DateTime.Now.Second;

        timer_onem.Change(Convert.ToInt64(tms) - wait, Timeout.Infinite);
    }

编辑1

我更改了间隔,使其每秒触发一次,然后检查分钟是否已更改。仍漂移

    timer_onem = new System.Threading.Timer(OnTimedEvent, null,
                                    (int)timeToStart.TotalMilliseconds, 1000);

    private static void OnTimedEvent(object o)
    {
        var minute = DateTime.Now.Minute;

        if (minute != lastMinute)
        {
            lastMinute = minute;
            CodeToExecute();
        }
    }

    private static void CodeToExecute()
    {
        if (bGenerate)
        {
            double tms = 1000;
            // code
            timer_onem.Change(Convert.ToInt64(tms), 1000);
        }
    }

1 个答案:

答案 0 :(得分:3)

Timer保证不会比Interval更快

所以你需要打电话,说每一秒,然后检查整整一分钟。

为了获得更好的精度,你必须每1/2秒或更好地检查一次。

信息理论的基本规则是,要以给定的分辨率(在您的情况下为1秒)进行测量,您需要采样的分辨率优于分辨率的两倍。因此,要测量20kHz,您需要的采样率优于2x20kHz,比如44.1kHz。 (识别数字?)

如果您不想通过经常来调用一个精确的时间点,那么您可以编写一些更复杂的代码。 Tick将剩余时间的Timer.Interval重置为一半,直到下一整分钟,直到500码以下为止。

但是,在设置预期时间的过程中,代码中存在相当复杂的事情;确保它们不是真正的问题。除非你收集&#39; 收集&#39; &#39; 错误..