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) { _tasks.Add(new ScheduledTask(name, timeOfDay, action)); } } /// /// 添加一个循环任务 /// /// /// /// /// 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); } } /// /// 执行任务 /// /// 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; } }); } } } } } }