-1

I have a function that runs every minute:

var waitHandle = new AutoResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(
    waitHandle,
    // Method to execute
    (state, timeout) =>
    {
        Console.WriteLine(DateTime.Now + " START");
        ..some stuff
        Console.WriteLine(DateTime.Now + " END");
    },
    null,
    TimeSpan.FromMinutes(1),
    false
);

This code executes well, but sample output is:

2016-08-16 18:45:55 START
2016-08-16 18:45:55 END
2016-08-16 18:46:55 START
2016-08-16 18:46:55 END

(or whatever second it happens to be at at the time of calling) I would like it to run like this:

2016-08-16 18:45:00 START
2016-08-16 18:45:00 END
2016-08-16 18:46:00 START
2016-08-16 18:46:00 END

So I want this function to run every minute, but when the seconds are at 0. How can I do that?

Raktim Biswas
  • 4,011
  • 5
  • 27
  • 32
Simon
  • 2,643
  • 3
  • 40
  • 61
  • 1
    http://stackoverflow.com/questions/1329900/net-event-every-minute-on-the-minute-is-a-timer-the-best-option?rq=1 – serhiyb Aug 16 '16 at 16:41
  • @serhiyb - I was wondering if there's a way of editing my code and the RegisterWaitForSingleObject method to do the same thing – Simon Aug 16 '16 at 16:43
  • [edit] your question to make it clear what you want, and why the solution you have is not working for you. – Heretic Monkey Aug 16 '16 at 16:45
  • what's wrong with the code right now? – Raktim Biswas Aug 16 '16 at 16:47
  • @MikeMcCaughan I edited it – Simon Aug 16 '16 at 16:51
  • @Rakitić I added what's wrong with it – Simon Aug 16 '16 at 16:51
  • See the marked duplicate for the answer. Note the advice offered as part of that Q&A that points out that you will _never_ be guaranteed execution exactly on the minute mark. You can get very close, but Windows isn't a real-time OS and can't provide real-time scheduling. Note also that your method of scheduling -- waiting on a wait handle with a timeout -- is a bit odd. .NET has a variety of timer implementations that would be better. – Peter Duniho Aug 16 '16 at 18:43

1 Answers1

1

Obviously, the problem is the initial offset you have to add to your code. It can be done easily, based on the second answer from the question linked by serhiyb:

void Register(AutoResetEvent waitHandle, TimeSpan timeout, 
    WaitOrTimerCallback callback, bool once)
{
    ThreadPool.RegisterWaitForSingleObject(waitHandle, callback, null, timeout, once);
}

void Callback(object state, bool isTimeout)
{
    Console.WriteLine(DateTime.Now + " START");
    //..some stuff
    Console.WriteLine(DateTime.Now + " END");
}

And then:

var waitHandle = new AutoResetEvent(false);

Register(
    waitHandle,
    TimeSpan.FromSeconds(60 - DateTime.Now.Second), //initial offset
    (state, isTimeout) =>
    {
        Callback(state, isTimeout);
        Register(waitHandle, TimeSpan.FromMinutes(1), Callback, false);
    },
    true);
galenus
  • 2,087
  • 16
  • 24