上的计划任务.Net Core



我需要使用将寡妇服务器的Scheduler任务中的几个计划任务转换为独立的应用程序。网

过去我在上用过Quartz。Net框架4.x,在基于不同调度器的多个长时间运行的任务方面存在一些小问题。

现在我正在使用。Net 5和我想知道是否有一种新的方式来安排任务,比如工人服务,或者使用Quartz仍然更好、更灵活。网

由于我需要运行从30秒到2小时的长时间任务,我需要使用系统创建一个定时后台任务。线程。计时器

代码应如下:

public Task StartAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Timed Hosted Service running.");
_timer = new Timer(DoSomething, null, TimeSpan.Zero, 
TimeSpan.FromHours(24));
return Task.CompletedTask;
}

并且它应该每24小时调用DoSomething。

我的疑虑是:

  • 它什么时候开始工作并计算24小时,当我第一次跑步时应用程序
  • 我怎么能说任务必须在一天中的特定时间,例如午夜
  • 工人服务是否适合管理计划任务

当我第一次运行应用程序时,它什么时候开始工作并计算24小时?

是。设置断点并启动应用程序。你会看到它燃烧的速度有多快。

辅助服务是否适合管理计划任务?

是。

我怎么能说任务必须在一天中的特定时间运行,例如午夜?

让我们看看这个代码:

public sealed class MyTimedBackgroundService : BackgroundService
{
private static int SecondsUntilMidnight()
{
return (int)(DateTime.Today.AddDays(1.0) - DateTime.Now).TotalSeconds;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var countdown = SecondsUntilMidnight();
while (!stoppingToken.IsCancellationRequested)
{
if (countdown-- <= 0)
{
try
{
await OnTimerFiredAsync(stoppingToken);
}
catch(Exception ex)
{
// TODO: log exception
}
finally
{
countdown = SecondsUntilMidnight();
}
}
await Task.Delay(1000, stoppingToken);
}
}
private async Task OnTimerFiredAsync(CancellationToken stoppingToken)
{
// do your work here
Debug.WriteLine("Simulating heavy I/O bound work");
await Task.Delay(2000, stoppingToken);
}
}

这根本不使用System.Threading.Timer,因为你担心计时器因为某些边界而永远不会真正启动。有些人对此感到偏执。我从来没有遇到过这种情况。我经常在这类工作中使用Timer

它将计算到午夜的秒数,然后循环直到到达那里。

这是一个不可重入的计时器,由于处理延迟的业务逻辑,会有轻微的时间延迟。

以下是使用System.Threading.Timer:的另一个示例

public sealed class MyTimedBackgroundService : IHostedService
{
private Timer _t;
private static int MilliSecondsUntilMidnight()
{
return (int)(DateTime.Today.AddDays(1.0) - DateTime.Now).TotalMilliseconds;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// set up a timer to be non-reentrant
_t = new Timer(async _ => await OnTimerFiredAsync(cancellationToken),
null, MilliSecondsUntilMidnight(), Timeout.Infinite);
}
public Task StopAsync(CancellationToken cancellationToken)
{
_t?.Dispose();
return Task.CompletedTask;
}
private async Task OnTimerFiredAsync(CancellationToken cancellationToken)
{
try
{
// do your work here
Debug.WriteLine("Simulating heavy I/O bound work");
await Task.Delay(2000, cancellationToken);
}
finally
{
// set timer to fire off again
_t?.Change(MilliSecondsUntilMidnight(), Timeout.Infinite);
}
}
}

(此代码未经测试,可能存在一些拼写/语法错误(

这是一个不可重入的计时器,这意味着如果它当前正在处理数据,您可以保证它不会再次启动。

它将计算到午夜的毫秒数,然后根据该计算设置计时器。

这个想法来自微软。

这两个例子都可以这样注入:

services.AddHostedService<MyTimedBackgroundService>();

云原生警告:

请记住,由于这些示例是应用程序的本地示例,如果应用程序在有多个实例运行的情况下水平扩展,则您将在单独的进程中运行两个或多个计时器。只是一个友好的提醒。如果您的应用程序永远无法扩展,请忽略此警告。

最新更新