using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Api.Utility { public class TaskScheduler { /// /// 任务计划管理器实例,可以直接使用 /// public static TaskScheduler Shared { get; } = new(); private readonly List _tasks = []; private readonly List _recurringTasks = []; private readonly Timer _timer; private readonly Lock _lock = new(); /// /// 创建一个轻量级的任务计划管理器 /// public TaskScheduler() { _timer = new Timer(CheckAndRunTasks, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); _timer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(1)); } /// /// 添加一个任务计划 /// /// /// /// public void AddTask(string name, TimeSpan timeOfDay, Action action) { lock (_lock) { ScheduledTask task = new(name, timeOfDay, action); if (DateTime.Now > DateTime.Today.Add(timeOfDay)) { task.LastRun = DateTime.Today.Add(timeOfDay); } _tasks.Add(task); } } /// /// 添加一个循环任务 /// /// /// /// /// public void AddRecurringTask(string name, TimeSpan interval, Action action, bool startNow = false) { lock (_lock) { DateTime now = DateTime.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, 0); DateTime nextRun = startNow ? now : now.Add(interval); RecurringTask recurringTask = new(name, interval, action) { NextRun = nextRun }; _recurringTasks.Add(recurringTask); } } /// /// 移除任务计划 /// /// public void RemoveTask(string name) { lock (_lock) { int removeTasks = _tasks.RemoveAll(t => t.Name == name); int removeRecurringTasks = _recurringTasks.RemoveAll(t => t.Name == name); } } /// /// 获取任务计划上一次执行时间 /// /// /// /// public DateTime GetLastTime(string name, bool recurring = false) { if (!recurring) { if (_tasks.FirstOrDefault(t => t.Name == name) is ScheduledTask task && task.LastRun.HasValue) { return task.LastRun.Value; } else if (_recurringTasks.FirstOrDefault(t => t.Name == name) is RecurringTask recurringTask && recurringTask.LastRun.HasValue) { return recurringTask.LastRun.Value; } } else if (_recurringTasks.FirstOrDefault(t => t.Name == name) is RecurringTask recurringTask && recurringTask.LastRun.HasValue) { return recurringTask.LastRun.Value; } return DateTime.MinValue; } /// /// 获取任务计划下一次执行时间 /// /// /// /// public DateTime GetNextTime(string name, bool recurring = false) { if (!recurring) { if (_tasks.FirstOrDefault(t => t.Name == name) is ScheduledTask task) { DateTime today = DateTime.Today.Add(task.TimeOfDay); return task.IsTodayRun ? today.AddDays(1) : today; } else if (_recurringTasks.FirstOrDefault(t => t.Name == name) is RecurringTask recurringTask) { return recurringTask.NextRun; } } else if (_recurringTasks.FirstOrDefault(t => t.Name == name) is RecurringTask recurringTask) { return recurringTask.NextRun; } return DateTime.MaxValue; } public string GetRunTimeInfo(string name) { DateTime last = GetLastTime(name); DateTime next = GetNextTime(name); string msg = ""; if (last != DateTime.MinValue) { msg += $"上次运行时间:{last.ToString(General.GeneralDateTimeFormat)}\r\n"; } if (next != DateTime.MaxValue) { msg += $"下次运行时间:{next.ToString(General.GeneralDateTimeFormat)}\r\n"; } if (msg != "") { msg = $"任务计划:{name}\r\n{msg}"; } else { msg = $"任务计划 {name} 不存在!"; } return msg.Trim(); } /// /// 执行任务 /// /// private void CheckAndRunTasks(object? state) { lock (_lock) { DateTime now = DateTime.Now; foreach (ScheduledTask task in _tasks) { if (!task.IsTodayRun) { if (now.TimeOfDay >= task.TimeOfDay && now.TimeOfDay < task.TimeOfDay.Add(TimeSpan.FromSeconds(10))) { task.LastRun = now; ThreadPool.QueueUserWorkItem(_ => { try { task.Action(); } catch (Exception ex) { task.Error = ex; } }); } } } foreach (RecurringTask recurringTask in _recurringTasks) { if (now >= recurringTask.NextRun) { recurringTask.LastRun = now; recurringTask.NextRun = recurringTask.NextRun.Add(recurringTask.Interval); ThreadPool.QueueUserWorkItem(_ => { try { recurringTask.Action(); } catch (Exception ex) { recurringTask.Error = ex; } }); } } } } } }