簡體   English   中英

如何在一天中的特定時間運行 .net Core IHosted 服務?

[英]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 作業

  1. 創建 ASP.NET Core Web 項目

  2. 添加 NuGet 包 Microsoft.Extensions.Hosting

  3. 添加 NuGet 包 Cronos

  4. 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(); } }
  5. 繼承自 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); } }
  6. 添加新接口IScheduleConfig

     public interface IScheduleConfig<T> { string CronExpression { get; set; } TimeZoneInfo TimeZoneInfo { get; set; } }
  7. 實現 IScheduleConfig

     public class ScheduleConfig<T> : IScheduleConfig<T> { public string CronExpression { get; set; } public TimeZoneInfo TimeZoneInfo { get; set; } }
  8. 添加擴展類 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; } }
  9. 使用泛型調度多個 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM