[英]How to run .net Core IHosted Service at specific time Of the day?
我有以下計時器在 .Net 核心 Ihosted 服務中運行,
TimeSpan ScheduledTimespan;
string[] formats = { @"hh\:mm\:ss", "hh\\:mm" };
string strTime = Startup.Configuration["AppSettings:JobStartTime"].ToString();
var success = TimeSpan.TryParseExact(strTime, formats, CultureInfo.InvariantCulture, out ScheduledTimespan);
Timer _timer = new Timer(JobToRun, null, TimeSpan.Zero, ScheduledTimespan);
我正在使用這個特定的重載,
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period);
但是一旦控制權到達它, JobToRun
就會執行。 如何讓它在每天的特定時間運行? 提前致謝。
以下函數返回解析的作業運行時間
private static TimeSpan getScheduledParsedTime()
{
string[] formats = { @"hh\:mm\:ss", "hh\\:mm" };
string jobStartTime = "07:10";
TimeSpan.TryParseExact(jobStartTime, formats, CultureInfo.InvariantCulture, out TimeSpan ScheduledTimespan);
return ScheduledTimespan;
}
以下函數返回從當天當前時間開始的延遲時間。 如果當天的當前時間超過了作業運行時間,則會在作業運行中添加適當的延遲,如下所示,
private static TimeSpan getJobRunDelay()
{
TimeSpan scheduledParsedTime = getScheduledParsedTime();
TimeSpan curentTimeOftheDay = TimeSpan.Parse(DateTime.Now.TimeOfDay.ToString("hh\\:mm"));
TimeSpan delayTime = scheduledParsedTime >= curentTimeOftheDay
? scheduledParsedTime - curentTimeOftheDay
: new TimeSpan(24, 0, 0) - curentTimeOftheDay + scheduledParsedTime;
return delayTime;
}
下面的計時器每天methodToExecute
根據JobRunDelay
調用JobRunDelay
_timer = new Timer(methodToExecute, null, getJobRunDelay(), new TimeSpan(24, 0, 0));
使用 Cron 作業
創建 ASP.NET Core Web 項目
添加 NuGet 包 Microsoft.Extensions.Hosting
添加 NuGet 包 Cronos
Crete 抽象類 CronJobService——在這個 CronJobService 中,我們使用一個定時器來跟蹤時間,並在時間達到預定時間時觸發后台任務
public abstract class CronJobService : IHostedService, IDisposable { private System.Timers.Timer _timer; private readonly CronExpression _expression; private readonly TimeZoneInfo _timeZoneInfo; protected CronJobService(string cronExpression, TimeZoneInfo timeZoneInfo) { _expression = CronExpression.Parse(cronExpression); _timeZoneInfo = timeZoneInfo; } public virtual async Task StartAsync(CancellationToken cancellationToken) { await ScheduleJob(cancellationToken); } protected virtual async Task ScheduleJob(CancellationToken cancellationToken) { var next = _expression.GetNextOccurrence(DateTimeOffset.Now, _timeZoneInfo); if (next.HasValue) { var delay = next.Value - DateTimeOffset.Now; if (delay.TotalMilliseconds <= 0) // prevent non-positive values from being passed into Timer { await ScheduleJob(cancellationToken); } _timer = new System.Timers.Timer(delay.TotalMilliseconds); _timer.Elapsed += async (sender, args) => { _timer.Dispose(); // reset and dispose timer _timer = null; if (!cancellationToken.IsCancellationRequested) { await DoWork(cancellationToken); } if (!cancellationToken.IsCancellationRequested) { await ScheduleJob(cancellationToken); // reschedule next } }; _timer.Start(); } await Task.CompletedTask; } public virtual async Task DoWork(CancellationToken cancellationToken) { await Task.Delay(5000, cancellationToken); // do the work } public virtual async Task StopAsync(CancellationToken cancellationToken) { _timer?.Stop(); await Task.CompletedTask; } public virtual void Dispose() { _timer?.Dispose(); } }
繼承自 CronJobService
public class XXXCronJob:CronJobService { private readonly ILogger<CronJob> _logger; public XXXCronJob(IScheduleConfig<CronJob > config, ILogger<CronJob> logger) : base(config.CronExpression, config.TimeZoneInfo) { _logger = logger; } public override Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("CronJob starts."); return base.StartAsync(cancellationToken); } public override Task DoWork(CancellationToken cancellationToken) { _logger.LogInformation($"{DateTime.Now:hh:mm:ss} CronJob is working."); return Task.CompletedTask; } public override Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("CronJob is stopping."); return base.StopAsync(cancellationToken); } }
添加新接口IScheduleConfig
public interface IScheduleConfig<T> { string CronExpression { get; set; } TimeZoneInfo TimeZoneInfo { get; set; } }
實現 IScheduleConfig
public class ScheduleConfig<T> : IScheduleConfig<T> { public string CronExpression { get; set; } public TimeZoneInfo TimeZoneInfo { get; set; } }
添加擴展類 ScheduledServiceExtensions
public static class ScheduledServiceExtensions { public static IServiceCollection AddCronJob<T>(this IServiceCollection services, Action<IScheduleConfig<T>> options) where T : CronJobService { if (options == null) { throw new ArgumentNullException(nameof(options), @"Please provide Schedule Configurations."); } var config = new ScheduleConfig<T>(); options.Invoke(config); if (string.IsNullOrWhiteSpace(config.CronExpression)) { throw new ArgumentNullException(nameof(ScheduleConfig<T>.CronExpression), @"Empty Cron Expression is not allowed."); } services.AddSingleton<IScheduleConfig<T>>(config); services.AddHostedService<T>(); return services; } }
使用泛型調度多個 Cron 作業
public void ConfigureServices(IServiceCollection services) { services.AddCronJob<XXXCronJob>(c => { c.TimeZoneInfo = TimeZoneInfo.Local; c.CronExpression = @"00 05 * * *"; }); services.AddCronJob<YYYCronJob>(c => { c.TimeZoneInfo = TimeZoneInfo.Local; c.CronExpression = @"00 08 * * *"; }); services.AddCronJob<ZZZCronJob>(c => { c.TimeZoneInfo = TimeZoneInfo.Local; c.CronExpression = @"30 14 * * *"; }); }
第一個是 05:00 AM。
第二個是 08:00 AM
最后一個是下午 14:30。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.