Sami In
Sami In

Reputation: 324

Where to put method call so it execute at every 5 minutes

I have below code :

public async Task StartAsync(CancellationToken cancellationToken)
{
    var cronExpressionVal = new Timer(async e => await GetCronExpression(cancellationToken), null, TimeSpan.Zero, new TimeSpan(0, 5, 0));
}

What I am trying to achieve is, GetCronExpression method should run at every 5 minutes.

But my problem is, when we first time run programme so it is coming in StartAsync method.

And it execute successfully.

Now it is not coming again in this method so my GetCronExpression method is not calling at every 5 minutes.

So my question is where should I put this GetCronExpression method call so it execute at every 5 minutes.

Upvotes: 0

Views: 1804

Answers (2)

Md Farid Uddin Kiron
Md Farid Uddin Kiron

Reputation: 22457

What I am trying to achieve is, GetCronExpression method should run at every 5 minutes.

Well, couple of ways to handle this. However, the most efficient and easiest way to meet your requirement is to use PeriodicTimer. Importantly, you don't need to think where should you keep this. You can call your method every 5 minutes time interval from everywhere. It could be within middleware or any custom class , repository, even from controller.

Implementation Using Middleware:

public class AutoTimerMiddleware
    {
        private readonly RequestDelegate _next;
        public AutoTimerMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        public async Task InvokeAsync(HttpContext httpContext)
        {


            var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));

            int counter = 0;
            while (await timer.WaitForNextTickAsync())
            {
                counter++;
               // if (counter > 5) break;
                CallThisMethodEvery5Second(counter);
            }
            // Move forward into the pipeline
            await _next(httpContext);
        }
        public void CallThisMethodEvery5Second(int counter)
        {
            Console.WriteLine("Current counter: {0} Last Fired At: {1}", counter, DateTime.Now);
        }
    }

Note: When use in middleware, please register in program.cs file as following

app.UseMiddleware<AutoTimerMiddleware>();

Output:

enter image description here

Implementation Using Any Custom Class/Anywhere:

            var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));

            int counter = 0;
            while (await timer.WaitForNextTickAsync())
            {
                counter++;
                if (counter > 5) break;
                CallThisMethodEvery5Second(counter);
            }

Note: You will call your method GetCronExpression within the WaitForNextTickAsync so that will be called at your given time frame. For the demo, I am calling this in every 5 seconds.

Method To Call:

public void CallThisMethodEvery5Second(int counter)
        {
            Console.WriteLine("Current counter: {0} Last Fired At: {1}",counter, DateTime.Now);
        }

Output:

enter image description here

Upvotes: 2

Daniil
Daniil

Reputation: 306

You have to keep reference to timer otherwise it will be garbage collected:

As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.

https://learn.microsoft.com/en-us/dotnet/api/system.threading.timer?view=net-7.0#remarks

If it's not the case, I suggest including more context.

Upvotes: 1

Related Questions