У меня есть код ниже:
public async Task StartAsync(CancellationToken cancellationToken)
{
var cronExpressionVal = new Timer(async e => await GetCronExpression(cancellationToken), null, TimeSpan.Zero, new TimeSpan(0, 5, 0));
}
Я пытаюсь добиться того, чтобы метод GetCronExpression
запускался каждые 5 минут.
Но моя проблема в том, что когда мы впервые запускаем программу, она входит в метод StartAsync
.
И выполняется успешно.
Теперь он больше не появляется в этом методе, поэтому мой метод GetCronExpression
не вызывается каждые 5 минут.
Итак, мой вопрос: куда мне поместить вызов этого метода GetCronExpression
, чтобы он выполнялся каждые 5 минут.
Вы должны сохранить ссылку на таймер, иначе он будет собран мусором:
Пока вы используете таймер, вы должны сохранять ссылку на него. Как и любой управляемый объект, Timer подлежит сборке мусора, если на него нет ссылок. Тот факт, что таймер все еще активен, не препятствует его сбору.
https://learn.microsoft.com/en-us/dotnet/api/system.threading.timer?view=net-7.0#remarks
Если это не так, я предлагаю включить больше контекста.
Чего я пытаюсь добиться, так это того, что метод GetCronExpression должен работать в каждые 5 минут.
Ну, пара способов справиться с этим. Однако самый эффективный и простой способ удовлетворить ваши требования — использовать PeriodicTimer. Главное, вам не нужно думать, где это хранить. Вы можете вызывать свой метод каждый 5 minutes
временной интервал отовсюду. Это может быть в middleware
или any custom class
репозитории, даже из controller
.
Реализация с использованием промежуточного ПО:
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);
}
}
Примечание. При использовании в промежуточном программном обеспечении зарегистрируйтесь в файле program.cs
следующим образом.
app.UseMiddleware<AutoTimerMiddleware>();
Вывод:
Реализация с использованием любого пользовательского класса/в любом месте:
var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
int counter = 0;
while (await timer.WaitForNextTickAsync())
{
counter++;
if (counter > 5) break;
CallThisMethodEvery5Second(counter);
}
Примечание. Вы будете вызывать свой метод GetCronExpression
в пределах WaitForNextTickAsync
, чтобы он вызывался в указанный вами период времени. Для демонстрации я вызываю это каждые 5 секунд.
Способ вызова:
public void CallThisMethodEvery5Second(int counter)
{
Console.WriteLine("Current counter: {0} Last Fired At: {1}",counter, DateTime.Now);
}
Вывод: