Detail
Detail

Reputation: 805

Is it acceptable practice to create Tasks with long delays?

I'm creating a scheduler to fire events at specific times of the day, and to do this I'm spinning up Tasks (one at a time, i.e. the 'next' schedule only) with a Task.Delay of anything up to a few days delay. For example, after the last event fires on a Friday afternoon, I'll set up the next one which will be some time on Monday, so it could potentially be a TimeSpan of up to 3 days (~260,000,000 milliseconds).

Is this acceptable practice? I'm concerned that this won't be stable/robust enough for a production environment.

Here's some snippets of code to describe what I've put together:

private void SetNextEvent()
{
    TimeModel next = GetNextScheduledTime();
    Debug.WriteLine($"Next schedule [{next.TimeType}]: {next.Time.ToString("yyyy-MM-dd HH:mm:ss")}");

    TimeSpan delay = next.Time.Subtract(DateTime.Now);
    Task.Run(async () =>
    {
        await Task.Delay(delay);
        FireEvent(next);
    });
}

private void FireEvent(TimeModel time)
{
    Debug.WriteLine($"Event fired [{time.TimeType}]: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
    OnSchedulerEvent?.Invoke(this, new SchedulerEventArgs { ScheduleType = time.TimeType });
    if (_running)
        SetNextEvent();
}

Upvotes: 4

Views: 317

Answers (3)

usr
usr

Reputation: 171178

This is totally reliable. .NET timers are very efficient. The biggest problem is that you must assume that your production apps can exit at any time. The reason that is easiest to understand is a bug that kills the process. Other reasons include reboots, app pool recycles, deployments, ....

So if you can recover your state after being killed this is fine. If you add a comment about specific concerns I'll address them.

It looks like you have a way to recover timers because you apparently can compute the next due time. Under those circumstances it's very safe to do this. You need to ensure that your code is always running e.g. right after a reboot or a crash.

Note, that IIS apps need to tolerate running multiple times concurrently. Otherwise, IIS is a great host for your scenario.

Upvotes: 3

Rodney Ringler
Rodney Ringler

Reputation: 11

I agree that the Windows Task Scheduler is probably the best approach is you know ahead of time the schedule to run the next task.

If you do not know this ahead of time(i.e. the time to wait for the next task can vary) then I would suggest using a timer and an event handler method when the timer expires.

Each time you can set the Interval property of the timer for the time to wait. When the time expires the timer event handler will run and it can execute the ask and reset the Interval for the timer. This seems a little cleaner then a Task.Delay.

Upvotes: 0

If you're running Windows, I'd use the TaskScheduler to do what you're trying to do.

run taskschd.msc you can use that program to schedule periodic tasks.

There should be an "Create Task..." button in the panel on the right.

Upvotes: 0

Related Questions