diff --git a/Falcon.SugarApi/TimedBackgroundTask/IServiceCollectionExtend.cs b/Falcon.SugarApi/TimedBackgroundTask/IServiceCollectionExtend.cs
new file mode 100644
index 0000000..03e1620
--- /dev/null
+++ b/Falcon.SugarApi/TimedBackgroundTask/IServiceCollectionExtend.cs
@@ -0,0 +1,22 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Falcon.SugarApi.TimedBackgroundTask
+{
+ ///
+ /// 服务集合扩展方法
+ ///
+ public static class IServiceCollectionExtend
+ {
+ ///
+ /// 向HostService中注册TimedBackgroundTask服务
+ ///
+ /// TimedBackgroundTask的具体类型
+ /// 服务集合
+ /// 服务集合
+ public static IServiceCollection AddTimedBackgroundTask(this IServiceCollection services)
+ where T : TimedTask {
+ services.AddHostedService();
+ return services;
+ }
+ }
+}
diff --git a/Falcon.SugarApi/TimedBackgroundTask/TimedTask.cs b/Falcon.SugarApi/TimedBackgroundTask/TimedTask.cs
new file mode 100644
index 0000000..fadd64b
--- /dev/null
+++ b/Falcon.SugarApi/TimedBackgroundTask/TimedTask.cs
@@ -0,0 +1,135 @@
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Falcon.SugarApi.TimedBackgroundTask
+{
+ ///
+ /// 由定时器驱动的后台任务
+ ///
+ public class TimedTask:BackgroundService, IDisposable
+ {
+ ///
+ /// 日志记录器
+ ///
+ protected readonly ILogger? Logger;
+ ///
+ /// 心跳计时器
+ ///
+ private readonly PeriodicTimer _timer;
+
+ ///
+ /// 运行一次任务
+ ///
+ /// 退出信号
+ /// 如果继续执行返回True,否则False
+ public virtual async Task Run(CancellationToken cancellationToken) => await Task.FromResult(true);
+
+ ///
+ /// Timer心跳
+ ///
+ public virtual int Heartbeat { get; set; } = 1;
+
+ ///
+ /// 执行计划的Cron串
+ ///
+ public virtual string CronSchedule { get; set; } = "30 * * * * *";
+
+ ///
+ /// 获取下次执行任务的计划
+ ///
+ public CronExpression Schedule { get; private set; }
+
+ ///
+ /// 任务正在运行
+ ///
+ private bool _isRunning = false;
+ ///
+ /// 下次执行时间
+ ///
+ public DateTime NextTickTime { get; set; } = DateTime.MinValue;
+
+ ///
+ /// 后台任务开始
+ ///
+ protected virtual void OnStart(TimedTask t,CancellationToken stoppingToken) { }
+ ///
+ /// 后台任务停止
+ ///
+ protected virtual void OnStop(TimedTask t,CancellationToken stoppingToken) { }
+ ///
+ /// 完成一次执行
+ ///
+ protected virtual void OnCompleted(TimedTask t,CancellationToken stoppingToken) { }
+ ///
+ /// 执行中发生未处理异常
+ ///
+ protected virtual bool OnException(TimedTask t,Exception ex,CancellationToken stoppingToken) {
+ return false;
+ }
+ ///
+ /// 系统服务
+ ///
+ public IServiceProvider Service { get; set; }
+ ///
+ /// 资源锁
+ ///
+ private static object _lock = new object();
+
+ ///
+ /// 构造Timed后台任务
+ ///
+ /// 服务提供器
+ public TimedTask(IServiceProvider service) {
+ this.Service = service;
+ this.Logger = service.GetService(typeof(ILogger<>).MakeGenericType(GetType())) as ILogger;
+ _timer = new PeriodicTimer(TimeSpan.FromSeconds(this.Heartbeat));
+ this.Schedule = new CronExpression(this.CronSchedule);
+ }
+
+ ///
+ /// 由系统调度执行任务
+ ///
+ /// 退出信号
+ /// 无返回
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
+ this.OnStart(this,stoppingToken);
+ while(await _timer.WaitForNextTickAsync(stoppingToken)) {
+ lock(_lock) {
+ if(stoppingToken.IsCancellationRequested) {
+ break;
+ }
+ if(this._isRunning || DateTime.Now < this.NextTickTime) {
+ continue;
+ }
+ this._isRunning = true;
+ }
+ try {
+ var goOn = await this.Run(stoppingToken);
+ this.OnCompleted(this,stoppingToken);
+ if(goOn) {
+ continue;
+ }
+ }
+ catch(Exception ex) {
+ this.OnException(this,ex,stoppingToken);
+ }
+ SetNextTick();
+ this._isRunning = false;
+ }
+ this.OnStop(this,stoppingToken);
+ }
+
+ private void SetNextTick(string? cronSchedule = null) {
+ var s = cronSchedule == null ? this.Schedule : new CronExpression(cronSchedule);
+ this.NextTickTime = s.GetNextOccurrence(DateTime.Now);
+ }
+
+ public override void Dispose() {
+ this._timer?.Dispose();
+ base.Dispose();
+ }
+ }
+}