Manikanta Dornala
Manikanta Dornala

Reputation: 1101

Repeated Tasks using Timer Interval vs Task Delay

I'm implementing a scheduled job like methods and have narrowed down to approaches. One that implements a Timer Interval and the other based on Task Delay.

I've also considered using Azure Timer triggered webjobs but they do not work in a multi-instance mode. Effectively in a multi-instance application only one trigger is fired in one of the instances and the others are locked, hence increasing the instance count of my application does not increase the number of events fired.

Method A (Timer Interval)

using System;
using System.Threading.Tasks;
using System.Timers;

public class Example
{
    public static void Main()
    {
        var aTimer = new Timer();
        aTimer.Interval = 5000;
        aTimer.Elapsed += OnTimedEventA;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;

        var bTimer = new System.Timers.Timer();
        bTimer.Interval = 2000;
        bTimer.Elapsed += OnTimedEventB;
        bTimer.AutoReset = true;
        bTimer.Enabled = true;

        Console.WriteLine("Press the Enter key to exit the program at any time... ");
        Console.ReadLine();
    }
    private static void OnTimedEventA(Object source, System.Timers.ElapsedEventArgs e)
    {
        Task.Run(() =>
        {
            Console.WriteLine("The Elapsed event A was raised at {0}", DateTime.Now);
        });
    }
    private static void OnTimedEventB(Object source, System.Timers.ElapsedEventArgs e)
    {
        Task.Run(() =>
        {
            Console.WriteLine("The Elapsed event B was raised at {0}", DateTime.Now);
        });
    }
}

Method B (Task Delay)

using System;
using System.Threading.Tasks;
public class Example
{
    public static void Main()
    {
        EventAAsync();
        EventBAsync();

        Console.WriteLine("Press the Enter key to exit the program at any time... ");
        Console.ReadLine();
    }
    private static async Task EventAAsync()
    {
        while (true)
        {
            Task.Run(() =>
            {
                Console.WriteLine("The Elapsed event A was raised at {0}", DateTime.Now);
            });
            await Task.Delay(TimeSpan.FromSeconds(5));
        }
    }
    private static async Task EventBAsync()
    {
        while (true)
        {
            Task.Run(() =>
            {
                Console.WriteLine("The Elapsed event B was raised at {0}", DateTime.Now);
            });
            await Task.Delay(TimeSpan.FromSeconds(2));
        }
    }
}

Both Method A and Method B, functionally do the same. They both call fire events A and B at regular intervals of 5s and 2s and forget. Now I'm trying to understand the pros and cons of both approaches. In the end, the events themselves run on separate threads. Theoretically and in practice which of the two should be adopted for handling many such event triggers to be scaled across multiple instances.

Any other methods are also welcome.

Upvotes: 19

Views: 21212

Answers (2)

Shinva
Shinva

Reputation: 2304

Method A is used when you have to trigger some task at regular intervals. Method B is used when you have to give regular intervals between the triggering of some task.

There is a difference if the event handler (task performed after the trigger) takes a longer time to process.

Method A : No matter how much time the task in the event handler takes, the event handler keeps getting triggered at the set time interval (code has to be reentrant).

Method B : Task completes then we sleep. So if the task takes different times to complete, the next trigger is also at different times

Upvotes: 16

M.kazem Akhgary
M.kazem Akhgary

Reputation: 19149

Use timer instead, while both use the same clock as noted by @Evk but first approach runs timer permanently.

Using Task.Delay will be just as accurate but there is a short gap between finished Delay and starting new Delay. After long period they can become desynchronized. So distance between 5 and 2 second intervals will not be same as time where you started timing.

Using Timer that runs permanently doesn't have this problem.

Upvotes: 3

Related Questions