开发者

Timer run every 5th minute

How can I run 开发者_如何学运维some function every 5th minute? Example: I want run sendRequest() only at time 14:00, 14:05, 14:10 etc.

I would like to do it programmatically, in C#. The application is a Windows service.


Use System.Threading.Timer. You can specify a method to call periodically.

Example:

Timer timer = new Timer(Callback, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));

public void Callback(object state) {
    Console.WriteLine("The current time is {0}", DateTime.Now);
}

You can use the second parameter to pass state to the callback.

Note that you'll need to keep your application alive somehow (e.g., run it as a service).

As for how to make sure that it runs at hh:mm where mm % 5 == 0, you can do the following.

DateTime now = DateTime.Now;
int additionalMinutes = 5 - now.Minute % 5;
if(additionalMinutes == 0) {
    additionalMinutes = 5;
}
var nearestOnFiveMinutes = new DateTime(
    now.Year,
    now.Month,
    now.Day,
    now.Hour,
    now.Minute,
    0
).AddMinutes(additionalMinutes);
TimeSpan timeToStart = nearestOnFiveMinutes.Subtract(now);
TimeSpan tolerance = TimeSpan.FromSeconds(1);
if (timeToStart < tolerance) {
    timeToStart = TimeSpan.Zero;
}

var Timer = new Timer(callback, null, timeToStart, TimeSpan.FromMinutes(5));

Note that the tolerance is necessary in case this code is executing when now is very close to the nearest hh:mm with mm % 5 == 0. You can probably get away with a value smaller than one second but I'll leave that to you.


The answer posted six years ago is useful. However, IMHO with modern C# it is now better to use the Task-based API with async and await. Also, I differ a little on the specifics of the implementation, such as how to manage the delay computation and how to round the current time to the next five minute interval.

First, let's assume the sendRequest() method returns void and has no parameters. Then, let's assume that the basic requirement is to run it roughly every five minutes (i.e. it's not that important that it run exactly on five-minute divisions of the hour). Then that can be implemented very easily, like this:

async Task RunPeriodically(Action action, TimeSpan interval, CancellationToken token)
{
    while (true)
    {
        action();
        await Task.Delay(interval, token);
    }
}

It can be called like this:

CancellationTokenSource tokenSource = new CancellationTokenSource();

Task timerTask = RunPeriodically(sendRequest, TimeSpan.FromMinutes(5), tokenSource.Token);

When tokenSource.Cancel() is called, the loop will be interrupted by the TaskCanceledException thrown at the await Task.Delay(...) statement. Otherwise, the sendRequest() method will be called every five minutes (with it being called immediately when the RunPeriodically() method is called…you can reorder the statements in the loop if you want it to wait the first time too).

That's the simplest version. If instead you do want to perform the action exactly on five minute intervals, you can do something similar, but compute the next run time and delay for an appropriate amount of time. For example:

// private field somewhere appropriate; it would probably be best to put
// this logic into a reusable class.
DateTime _nextRunTime;

async Task RunPeriodically(Action action,
    DateTime startTime, TimeSpan interval, CancellationToken token)
{
    _nextRunTime = startTime;

    while (true)
    {
        TimeSpan delay = _nextRunTime - DateTime.UtcNow;

        if (delay > TimeSpan.Zero)
        {                
            await Task.Delay(delay, token);
        }

        action();
        _nextRunTime += interval;
    }
}

Called like this:

CancellationTokenSource tokenSource = new CancellationTokenSource();
DateTime startTime = RoundCurrentToNextFiveMinutes();

Task timerTask = RunPeriodically(sendRequest,
    startTime, TimeSpan.FromMinutes(5), tokenSource.Token);

Where the helper method RoundCurrentToNextFiveMinutes() looks like this:

DateTime RoundCurrentToNextFiveMinutes()
{
    DateTime now = DateTime.UtcNow,
        result = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);

    return result.AddMinutes(((now.Minute / 5) + 1) * 5);
}

In either example, the timerTask object can be used to monitor the state of the loop. In most cases, it's probably not needed. But if you want to be able to, e.g. await until some other part of the code cancels the loop, this object is what you'd use.

Note that the Task.Delay() method does use a timer in its implementation. The above is not suggested for the purpose of avoiding the use of a timer, but rather to show an implementation of the original goal using the modern C# async/await features. This version will mesh more cleanly with other code that is already using async/await.


Use System.Threading.Timer:

var timer = new Timer(TimerTick, null, TimeSpan.Zero, new TimeSpan(0, 0, 0, 1));

int lastMinute = 1;

void TimerTick(object state)
{
    var minute = DateTime.Now.Minutes;
    if (minute != lastMinute && minute % 5 == 0)
    {
        lastMinute = minute;
        //do stuff
    }
}

This might look somewhat clumsy and inefficient since it has to call every second, but the actual number of CPU cycles that get used to perform the check once a second is totally negligible on virtually any hardware.

(Sorry if the code isn't 100% correct; I don't have an IDE on me right now.


You can make a thread which include a loop like this

void Runner(){
   while(1){
         Thread t = new thread( target_method );
         t.start();
         sleep(5 * 60 * 1000);
   }
}

It's a bit quick and dirty but gonna do the job :)


you could have a thread running that first

  1. checks how long to sleep until next 5th minute (so if it's 13:59:51, it sleeps for 9 seconds)
  2. does the action;
  3. then sleeps for 5 minutes
  4. goes to step 2


This class is everythign you need, you just setup the amount of time between delegate callings and your delegate and thats it :)

http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx


You better give you own Thread that executes the method a condition

While(programStatus == ProgramStatus.Working)
{
   While (true)
   {
      // Do your stuff
   }
   Thread.Sleep(TheTimeYouWantTheThreadToWaitTillTheNextOperation);
}


What you are looking for is code that implements 'cron' jobs. There are a few libraries out there that do this (quartz.net is one of them). I found that many of them are bulky and have many features. Here is a leaner implementation that I have used in some projects:

http://blog.bobcravens.com/2009/10/an-event-based-cron-scheduled-job-in-c/

P.S. My server appears to be down right now. I am working on that.

Hope that helps.

Bob


There are a few ways to do this, you can create a timer that runs every 5 minutes and start it when the time reaches one of the 5 minute intervals, or have it run every few seconds and check if the time is divisible by 5

System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); // create a new timer
timer.interval = 300000; //300000 = 5 minutes

then create a tick function and add an event handler

timer.Tick += new EventHandler(TimerTickHandler); //add the event handler
timer.Start(); //start the timer


I agree with Peter Duniho - modern C# is far better at this stuff.

I would suggest using Microsoft's Reactive Framework (NuGet "System.Reactive") and then you can do this:

IObservable<long> timer =
    Observable
        .Defer(() =>
        {
            var now = DateTimeOffset.Now;
            var result = new DateTimeOffset(now.Year, now.Month, now.Day, now.Hour, 0, 0, now.Offset);
            result = result.AddMinutes(((now.Minute / 5) + 1) * 5);
            return Observable.Timer(result, TimeSpan.FromMinutes(5.0));
        });

    timer.Subscribe(x => 
    {
        /* Your code here that run on the 5 minute every 5 minutes. */
    });

I get this kind of result:

2016/08/11 14:40:00 +09:30
2016/08/11 14:45:00 +09:30
2016/08/11 14:50:00 +09:30


http://www.csharphelp.com/2006/02/c-timer-demo/

http://dotnetperls.com/timer

Few tutorials on the time in C#

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜