0

I try to create a windows service to check my data has expired.

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        TimeSpan now = DateTime.Now.TimeOfDay;
        if (now.Hours == 14 & now.Minutes == 37 & now.Seconds == 0)
        {
            //do something...
        }
    }
}

I found this BackgroundWorker always check the current time.

Is this the correct way to use it?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Shawn Chen
  • 11
  • 1
  • Possibly relevant https://stackoverflow.com/questions/38207026/is-there-a-variant-of-task-delay-that-expires-after-real-time-passes-e-g-even – Charlieface Aug 12 '22 at 08:23
  • Related: [How to start my Worker Service on the hour](https://stackoverflow.com/questions/71883959/how-to-start-my-worker-service-on-the-hour) – Theodor Zoulias Aug 12 '22 at 11:14

2 Answers2

0

This loop will run continuously. If you want to run the background worker at a specific point in time then you can either make the thread sleep for the specific amount of time (Target time - current time) or a fixed interval before it polls for the execution window. Keep in mind that when you choose the latter you should allow the execution happen within a window than the exact time. Otherwise, the task may never execute!

Mayur Ekbote
  • 1,700
  • 1
  • 11
  • 14
-1

Thanks to Mayur Ekbote for giving me ideas.

Here is my solution:

while (!stoppingToken.IsCancellationRequested)
{
    DateTime now = DateTime.Now;
    DateTime work_point = new DateTime(now.Year, now.Month, now.Day, 18, 33, 00);
    if (work_point < now)
    {
        work_point = work_point + new TimeSpan(24,0,0);
    }
    DateTime start_check_point = work_point - new TimeSpan(0, 1, 0);
    DateTime end_check_point = work_point + new TimeSpan(0, 1, 0);
    if (now >= start_check_point && now <= end_check_point)
    {
        _logger.LogInformation("start program at {time}", DateTimeOffset.Now);
        try
        {
            //do something...
        }
        catch (Exception ex)
        {
            _logger.LogError("error msg", ex.Message);
        }
        finally
        {
            //Skip inspection period interval
            await Task.Delay(1000 * 60, stoppingToken);
        }
    }
    else
    {
        _logger.LogError($"Scheduled to run at {work_point.ToString("s")} ");
         //Pause the program until the check interval to avoid wasting performance
        await Task.Delay(start_check_point - now, stoppingToken);
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Shawn Chen
  • 11
  • 1
  • This is a bad solution as it locks up the windows service in an `await Task.Delay`. You need to use a proper Timer that can be stopped. – Enigmativity Aug 12 '22 at 10:56
  • @Enigmativity maybe the Windows service has nothing else to do until the specific time is reached. In which case this solution is good enough for the job. Arguably it might be even better than using a timer (for example a `System.Threading.Timer`), because it eliminates any possibility of overlapping execution. – Theodor Zoulias Aug 12 '22 at 11:20
  • @TheodorZoulias - My understanding was that the service wouldn't shutdown unless it co-operatively did? – Enigmativity Aug 13 '22 at 00:14
  • @Enigmativity I'm a newbie and most of the solutions are on my own. Maybe you can suggest me a clear solution? – Shawn Chen Aug 14 '22 at 09:04