C# .NET,每分钟事件(每分钟)。计时器是最好的选择吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1329900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:13:08  来源:igfitidea点击:

.NET, event every minute (on the minute). Is a timer the best option?

c#timersystem.reactive

提问by

I want to do stuff every minute on the minute (by the clock) in a windows forms app using c#. I'm just wondering whats the best way to go about it ?

我想在使用 c# 的 Windows 窗体应用程序中每分钟(按时钟)做一些事情。我只是想知道最好的方法是什么?

I could use a timer and set its interval to 60000, but to get it to run on the minute, I would have to enable it on the minute precisely, not really viable.

我可以使用计时器并将其间隔设置为 60000,但是要让它在每分钟运行,我必须精确地在每分钟启用它,这不是真的可行。

I could use a timer and set its interval to 1000. Then within its tick event, I could check the clocks current minute against a variable that I set, if the minute has changed then run my code. This worries me because I am making my computer do a check every 1 second in order to carry out work every 1 minutes. Surely this is ugly ?

我可以使用计时器并将其间隔设置为 1000。然后在其滴答事件中,我可以根据我设置的变量检查时钟当前分钟,如果分钟已更改,则运行我的代码。这让我很担心,因为我让我的电脑每 1 秒检查一次,以便每 1 分钟执行一次工作。这肯定是丑陋的?

I'm using windows forms and .Net 2.0 so do not want to use the DispatchTimer that comes with .Net 3.5

我正在使用 Windows 窗体和 .Net 2.0,所以不想使用 .Net 3.5 附带的 DispatchTimer

This must be a fairly common problem. Have any of you a better way to do this?

这应该是一个相当普遍的问题。你们有没有更好的方法来做到这一点?

回答by Walt W

Running a bit of code to see if the minute has changed once per second should not require much CPU time, and should be acceptable.

运行一些代码以查看分钟是否每秒更改一次应该不需要太多 CPU 时间,并且应该是可以接受的。

回答by Noldorin

Creating a Timercontrol that fires every 1 second (and usually does nothing but a simple check) will add negligibleoverhead to your application.

创建一个Timer每 1 秒触发一次的控件(通常只做一个简单的检查)将为您的应用程序增加可以忽略不计的开销。

Simply compare the value of Environment.TickCountor DateTime.Nowto the last stored time (the previous 'minute tick'), and you should have a reasonably precise solution. The resolution of these two time values is about 15ms, which should be sufficient for your purposes.

只需将Environment.TickCount或的值DateTime.Now与上次存储的时间(前一个“分钟刻度”)进行比较,您就应该有一个相当精确的解决方案。这两个时间值的分辨率约为 15 毫秒,对于您的目的来说应该足够了。

Do note however that the interval of the Timercontrol is not guaranteedto be that precise or even anywhere now, since it runs on the Windows message loop, which is tied in with the responsiveness of the UI. Never rely on it for even moderately precise timing - though it is good enough for firing repeating events where you can check the time using a more sensitive methodsuch as one of the two given above.

但是请注意,Timer控件的间隔不能保证那么精确,甚至现在任何地方都不能保证,因为它在 Windows 消息循环上运行,这与 UI 的响应性有关。即使是中等精确的计时也不要依赖它 - 尽管它足以触发重复事件,您可以使用更敏感的方法(例如上面给出的两种方法之一)检查时间。

回答by Charles Bretana

Use a timer set to run every second (or millisecond, whatever your accuracy threshold is), and then code the method to run your functionality if and only if the current time is within that threshold past the "on the minute" point.

使用设置为每秒(或毫秒,无论您的准确度阈值是多少)运行的计时器,然后编码该方法以运行您的功能,当且仅当当前时间在该阈值内超过“分钟”点时。

回答by Brian Surowiec

What I'm using for scheduled tasks is a System.Threading.Timer(System.Threading.TimerCallback, object, int, int) with the callback set to the code I want to execute based on the interval which is supplied in milliseconds for the period value.

我用于计划任务的是 System.Threading.Timer(System.Threading.TimerCallback, object, int, int) ,回调设置为我想根据以毫秒为单位提供的间隔执行的代码期间值。

回答by aquinas

How about:

怎么样:

int startin = 60 - DateTime.Now.Second;
var t = new System.Threading.Timer(o => Console.WriteLine("Hello"), 
     null, startin * 1000, 60000);

回答by Greg

What about a combination of aquinas' answer and 'polling': (apologies for the mixture of languages)

阿奎那的回答和“民意调查”的结合怎么样:(为语言混合道歉)

def waitForNearlyAMinute:
    secsNow = DateTime.Now.Second;
    waitFor = 55 - secsNow;
    setupTimer(waitFor, pollForMinuteEdge)

def pollForMinuteEdge:
    if (DateTime.Now.Second == 0):
        print "Hello, World!";
        waitForNearlyAMinute();
    else:
        setupTimer(0.5, pollForMinuteEdge)

回答by Jayden

You could set up two timers. An initial short interval timer (perhaps to fire every second, but dependent on how presice the second timer must fire on the minute).

你可以设置两个定时器。一个初始的短间隔计时器(可能每秒触发一次,但取决于第二个计时器必须在每分钟触发的精确程度)。

You would fire the short interval timer only until the desired start time of the main interval timer is reached. Once the initial time is reached, the second main interval timer can be activated, and the short interval timer can be deactivated.

您将只触发短间隔计时器,直到达到主间隔计时器所需的开始时间。一旦达到初始时间,第二个主间隔定时器可以被激活,并且短间隔定时器可以被停用。

void StartTimer()
{

  shortIntervalTimer.Interval = 1000;
  mainIntervalTimer.Interval = 60000; 

  shortIntervalTimer.Tick += 
    new System.EventHandler(this.shortIntervalTimer_Tick);
  mainIntervalTimer.Tick += 
    new System.EventHandler(mainIntervalTimer_Tick);

  shortIntervalTimer.Start();

}

private void shortIntervalTimer_Tick(object sender, System.EventArgs e)
{
  if (DateTime.Now.Second == 0)
    {
      mainIntervalTimer.Start();
      shortIntervalTimer.Stop();
    }
}

private void mainIntervalTimer_Tick(object sender, System.EventArgs e)
{
  // do what you need here //
}

回答by Jehof

What about Quartz.NET? I think its a good framework to do timed actions.

Quartz.NET怎么样?我认为这是一个很好的框架来执行定时操作。

回答by Ron Warholic

Alternatively, you could sleep to pause execution until it times out which should be close to your desired time. This will only wake the computer when the sleep finishes so it'll save you CPU time and let the CPU power down between processing events.

或者,您可以休眠以暂停执行,直到它超时,这应该接近您想要的时间。这只会在睡眠结束时唤醒计算机,因此它会节省您的 CPU 时间并让 CPU 在处理事件之间断电。

This has the advantage of modifying the timeout so that it will not drift.

这具有修改超时的优点,使其不会漂移。

int timeout = 0;

while (true)  {
  timeout = (60 - DateTime.Now.Seconds) * 1000 - DateTime.Now.Millisecond;
  Thread.Sleep(timeout);

  // do your stuff here
}

回答by Jared

Building on the answer from aquinas which can drift and which doesn't tick exactly on the minute just within one second of the minute:

以阿奎那的答案为基础,该答案可以漂移并且不会在一分钟的一秒内准确地在分钟上滴答作响:

static System.Timers.Timer t;

static void Main(string[] args)
{
    t = new System.Timers.Timer();
    t.AutoReset = false;
    t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
    t.Interval = GetInterval();
    t.Start();
    Console.ReadLine();
}

static double GetInterval()
{
    DateTime now = DateTime.Now;
    return ((60 - now.Second) * 1000 - now.Millisecond);
}

static void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine(DateTime.Now.ToString("o"));
    t.Interval = GetInterval();
    t.Start();
}

On my box this code ticks consistently within .02s of each minute:

在我的盒子上,这段代码在每分钟的 0.02 秒内持续滴答:

2010-01-15T16:42:00.0040001-05:00
2010-01-15T16:43:00.0014318-05:00
2010-01-15T16:44:00.0128643-05:00
2010-01-15T16:45:00.0132961-05:00