Reputation: 324
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
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:
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:
Upvotes: 2
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