定时器一旦上了分钟一分钟 [英] Timer once a minute on the minute

查看:216
本文介绍了定时器一旦上了分钟一分钟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不能得到定时器火一旦上了minue一分钟,1:00,1:01,1:02等相反,当定时器由几秒钟执行漂移每次迭代



 内部空隙startTimer所()
{
的DateTime nowEastern = CalendarEntity.Calendar.GetEasternTime();

INT secondsInterval = 5;

双additionalSeconds = secondsInterval - nowEastern.TimeOfDay.TotalSeconds%secondsInterval;
如果(additionalSeconds == 0)
{
additionalSeconds = 1;
}
变种nearestOnOneMinutes =新日期时间(
nowEastern.Year,
nowEastern.Month,
nowEastern.Day,
nowEastern.Hour,
nowEastern.Minute,
nowEastern.Second
).AddSeconds(additionalSeconds);

时间跨度timeToStart = nearestOnOneMinutes.Subtract(nowEastern);
时间跨度公差= TimeSpan.FromSeconds(1);
如果(timeToStart<公差)
{
timeToStart = TimeSpan.Zero;
}

timer_onem =新System.Threading.Timer(OnTimedEvent,空,
(INT)timeToStart.TotalMilliseconds,Timeout.Infinite);
}

私有静态无效OnTimedEvent(对象o)
{
变种分钟= DateTime.Now.Minute;
VAR秒= DateTime.Now.Second;
如果(分钟=最后一分钟和放大器;!&安培;第二个%60℃; 2)
{
=最后一分钟分钟;
CodeToExecute();
}
}

静态无效CodeToExecute()
{
双TMS = 60000;这里

//代码
INT等待= 60 - System.DateTime.Now.Second;

timer_onem.Change(Convert.ToInt64(TMS) - 等待,Timeout.Infinite);
}

修改1



我改变的时间间隔,以便它触发一次一秒钟,然后检查分钟发生了变化。尽管如此漂移

  timer_onem =新System.Threading.Timer(OnTimedEvent,空,
(INT)timeToStart.TotalMilliseconds, 1000);

私有静态无效OnTimedEvent(对象o)
{
变种分钟= DateTime.Now.Minute;

如果(分钟=最后一分钟!)
{
=最后一分钟分钟;
CodeToExecute();
}
}

私有静态无效CodeToExecute()
{
如果(bGenerate)
{
双TMS = 1000 ;
//代码
timer_onem.Change(Convert.ToInt64(TMS),1000);
}
}


解决方案

一个定时仅在保证是没有更快间隔



所以,你需要调用它,说每一秒钟并检查全分钟。



有关更好的精确度,你会检查每1/2秒或更高。



这是信息理论的一个基本规则,即与给定的分辨率(在你的案件1秒)衡量你需要有超过两倍该决议更好地品尝。因此,衡量20kHz的你需要一个smpling速度比2x20kHz好,说44.1。 (认识数字?)



如果你不想这么往往称它为仅仅让有一个在精确的时间点,你可以写一个涉及多一点的代码,每个勾选重置 Timer.Interval 来一小下的剩余时间的一半,直到下一整分钟,直到它在说500毫秒。



有相当复杂的事情怎么回事你的代码WRT,以建立在预期的时间,虽然,一定要确保他们不是真正的问题。应有的不可以成长从计时器的精度不够漂移,除非你'收集的错误。


I can't get the timer to fire once a minute on the minue, 1:00, 1:01, 1:02 etc. Instead, when the timer executes drifts by a couple of seconds each iteration

   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);
    }

EDIT 1

I changed the interval so that it fires once a second and then check that the minute has changed. Still drifts

    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);
        }
    }

解决方案

A Timer is only guaranteed to be no faster than Interval.

So you need to call it, say every second and check for the full minute.

For even better precision you would have to check every 1/2 second or better.

It is a basic rule of information theory that says that to measure with a given resolution (1 second in your case) you need to sample with better than twice that resolution. Hence to measure 20kHz you need a smpling rate better than 2x20kHz, say 44.1kHz. (Recognize the numbers?)

If you don't want to call it so often for simply getting one precise point in time, you could write a little more involved code that on each Tick resets the Timer.Interval to a little under half of the remaining time until the next full minute until it is under say 500ms..

There are rather complex things going on in your code wrt to setting up the expected time, though; do make sure they are not the real problem. There should not be a growing drift from the timer's lack of precision, unless you 'collect' the errors..

这篇关于定时器一旦上了分钟一分钟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆