Conditional logic based on time of day?

Viewed 154

I would like to run code conditionally based on the time of day. The code is within a while loop in several worker tasks that run throughout my programs lifetime. Performing the comparison on every loop iteration seems wasteful, is there a more efficient way to get this desired result?

The restate my question in code, I am asking if there is a more efficient to duplicate this functionality, perhaps using timers or some other scheduling mechanism:

while( workerNotCanceled )
{
    var time = DateTime.Now;
    if (time.Hour > 8 and time.Hour < 16)
        DoWork();
}
2 Answers

I don't know what DoWork() does, but it's quite probable that the time comparison is neglectable compared to it. You will only have a lot of time comparisons after 16:00 o'clock and before 8:00 o'clock. If the loop is entered outside the time frame, you could block the thread until it should do its work. If it is after 16:00 o'clock, it will sleep until the next day 8:00 o'clock, if it's before 8 o'clock, it will sleep until the same day 8:00 o'clock. Note that when you use Thread.Sleep you will be unable to cancel the loop outside the working time frame. If you want to do this, you can use a cancellation token.

while( workerNotCanceled )
{
    var time = DateTime.Now;
    if (time.Hour > 8 and time.Hour < 16)
        DoWork();
    else if(time.Hour >= 16)
    {
       DateTime nextStart = DateTime.Now.Date.AddDays(1).AddHours(8);
       Thread.Sleep(nextStart - DateTime.Now);
    }
    else
    {
       DateTime nextStart = DateTime.Now.Date.AddHours(8);
       Thread.Sleep(nextStart - DateTime.Now);
    }
}

So, I figure there would be different ways to approach this. If I had to do it, I probably would go for some variation of the strategy pattern and divide & conquer.

Divide & Conquer:

Separate switching / time checking from the actual job. So, I'd find some way to exchange a "do the job" strategy to a "do nothing" or "drop job" strategy.

That could be done using Quartz or a similar scheduling framework inside the app, which would trigger "switch off" and "switch on" jobs at the appropriate times.

Same could be done with cron or windows task scheduler which could trigger an api in your app. This opens up an attack vector, though.

Strategy pattern

That's relatively simple here: You'd have an interface with two implementations. The "switch on/off" jobs then simply "plug in" the appropriate implementation.

Example:

interface IWorker{
     void DoWork(); // maybe with an argument
}

class ActiveWorker : IWorker
{
     public void DoWork()
     {
          workerService.DoWork(); // replace with whatever is appropriate for you.
     }
}

class InactiveWorker : IWorker
{
    public void DoWork()
    {
         // Maybe just do nothing?
         // Maybe actively drop a request?
    }
}

In your consumer, you'd then have

IWorker worker; // Setup initially based on DateTime.Now

void ConsumingLooper()
{
     //...
     worker.DoWork(); // Based on which impl. is set to 'worker' will
                      // either handle or drop
}

Don't forget to add measures to handle the case where the looper wants to call worker.DoWork() while it is switched out. I left it out for brevity and also there are many different ways to achieve it. You may want to pick your favorite.

Related