2 回答

TA貢獻(xiàn)1864條經(jīng)驗(yàn) 獲得超6個(gè)贊
這就是我處理此類事情的方式......在我的情況下,我需要在特定日期、特定時(shí)間啟動(dòng)服務(wù)并每隔 x 天重復(fù)一次。但我不知道這是否正是您要找的東西:)
public class ScheduleHostedService: BackgroundService
{
private readonly ILogger<ScheduleHostedService> _logger;
private readonly DaemonSettings _settings;
public ScheduleHostedService(IOptions<DaemonSettings> settings, ILogger<ScheduleHostedService> logger)
{
_logger = logger;
_settings = settings.Value;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
DateTime? callTime=null;
if (_settings.StartAt.HasValue)
{
DateTime next = DateTime.Today;
next = next.AddHours(_settings.StartAt.Value.Hour)
.AddMinutes(_settings.StartAt.Value.Minute)
.AddSeconds(_settings.StartAt.Value.Second);
if (next < DateTime.Now)
{
next = next.AddDays(1);
}
callTime = next;
}
if (_settings.StartDay.HasValue)
{
callTime = callTime ?? DateTime.Now;
callTime = callTime.Value.AddDays(-callTime.Value.Day).AddDays(_settings.StartDay.Value);
if (callTime < DateTime.Now)
callTime = callTime.Value.AddMonths(1);
}
if(callTime.HasValue)
await Delay(callTime.Value - DateTime.Now, stoppingToken);
else
{
callTime = DateTime.Now;
}
while (!stoppingToken.IsCancellationRequested)
{
//do smth
var nextRun = callTime.Value.Add(_settings.RepeatEvery) - DateTime.Now;
await Delay(nextRun, stoppingToken);
}
}
static async Task Delay(TimeSpan wait, CancellationToken cancellationToken)
{
var maxDelay = TimeSpan.FromMilliseconds(int.MaxValue);
while (wait > TimeSpan.Zero)
{
if (cancellationToken.IsCancellationRequested)
break;
var currentDelay = wait > maxDelay ? maxDelay : wait;
await Task.Delay(currentDelay, cancellationToken);
wait = wait.Subtract(currentDelay);
}
}
}
我編寫(xiě)了 Delay 函數(shù)來(lái)處理超過(guò) 28 天的延遲。

TA貢獻(xiàn)1840條經(jīng)驗(yàn) 獲得超5個(gè)贊
您可以考慮使用 .NET 的 Reactive 擴(kuò)展,并將其實(shí)現(xiàn)為帶有 Timer和Cancellation Token. 使用 aScheduler您可以確定最佳線程方法(請(qǐng)參閱此處)
下面的代碼片段可用于ExecuteAsync顯示任意 3 秒啟動(dòng)時(shí)間然后具有 60 秒到期日期的方法(可以是任何時(shí)間長(zhǎng)度。注意Timestamp()它允許使用整數(shù)傳遞本地時(shí)間。
CancellationToken cancellationToken = CancellationToken.None;
Observable
.Timer(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(60))
.Timestamp()
.ObserveOn(NewThreadScheduler.Default)
.Subscribe(
x =>
{
// do some task
} ,
cancellationToken);
- 2 回答
- 0 關(guān)注
- 356 瀏覽
添加回答
舉報(bào)