schweppes0x
schweppes0x

Reputation: 310

Start Task at specific time

I have an class which derives from IHostedService. In here I have the override method StartAsync as shown below:

public Task StartAsync(CancellationToken cancellationToken)
{
    _timer = new Timer(DoSomething, null, offset, TimeSpan.FromHours(1));
    return Task.CompletedTask;
}

In here I have the variable offset which is of the TimeSpan class.

What I need:

I need to calculate the offset in such way that the task "DoSomething" will be executed every start of an hour, like: 10:00, 13:00, 21:00 or 00:00. So this offset needs to be in minutes.

Example : Let's say the application starts running at 13:48PM, the correct offset would be 12 minutes and the next hour would be 14.

My question: How would I calculate the offset which is in minutes until next hour ?

Upvotes: 1

Views: 2868

Answers (3)

Arsen Mkrtchyan
Arsen Mkrtchyan

Reputation: 50712

In the Microsoft Documentation, there is official version of TimedHostedService class

You can use cron parsing nuget pacakge (NCronTab.signed) to calculate the time based on configuration, and it will become a nice looking solution

public class TimedHostedService : IHostedService, IDisposable
{
    private readonly ILogger<TimedHostedService> _logger;
    private Timer _timer;
    private readonly CrontabSchedule _cronSchedule;

    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
        _cronSchedule = CrontabSchedule.Parse("0 * * * *");
    }

    public Task StartAsync(CancellationToken stoppingToken)
    {
        var now = DateTime.Now;
        var nextOccurance = _cronSchedule.GetNextOccurrence(now);
        _logger.LogInformation("Configuring next run at: {time}", nextOccurance);
            
        await Task.Delay(nextOccurance - now, stoppingToken);

        DoWork()

        return Task.CompletedTask;
    }

    private void DoWork()
    {
        
        _logger.LogInformation(
            "Timed Hosted Service is working. Count: {Count}", count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Upvotes: 1

schweppes0x
schweppes0x

Reputation: 310

My answer would be:

TimeSpan offset = TimeSpan.FromMinutes(60 - DateTimeOffset.UtcNow.Minute);

But is there any other (better)way to implement this ?

Upvotes: 0

draz
draz

Reputation: 836

something like

var minutes = (DateTime.Today.AddHours(DateTime.Now.Hour+1)-DateTime.Now).TotalMinutes

should do the trick

Upvotes: 2

Related Questions