using Apewer; using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Threading; namespace Apewer.Web { /// Cron 调度器。 public sealed class CronInvoker { #region Instance private List _assemblies = null; private List _instances = null; private bool _break = false; private Action _log = null; /// 获取或设置 Log 处理程序。 public Action LogAction { get { return _log; } set { _log = value; } } internal void Log(params object[] content) => Logger?.Text(typeof(CronInvoker), content); /// 加载程序集。 public void Load(IEnumerable assemblies) { Log("开始加载程序集。"); if (_assemblies == null) _assemblies = new List(); if (_assemblies.Count > 0) { Log("程序集列表为空。"); return; } if (assemblies == null) { _assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies()); } else { foreach (var assembly in assemblies) { if (assembly == null) continue; if (_assemblies.Contains(assembly)) continue; _assemblies.Add(assembly); } } var count = _assemblies.Count.ToString(); Log($"已加载 {count} 个程序集。"); } /// 通知打断循环,所有 Cron 执行结束后退出。 public void Break() { _break = true; } /// 开始 Cron 调用。 public void Start() { if (_instances != null) return; _instances = GetInstances(); var count = _assemblies.Count.ToString(); Log($"检查到 {count} 个 Cron 类型。"); foreach (var i in _instances) Log(i.Type.FullName); while (true) { // CronLog.Write("Tick"); var alive = 0; foreach (var i in _instances) { // 跳出。 if (i.Alive) alive++; if (_break) { i.Break = true; break; } // 当前线程正在活动。 if (i.Alive) { i.Latest = true; continue; } // 记录 Cron 结束时间,根据结束时间判断再次启动 Cron。 if (i.Latest) { Log($"类型 {i.Type.FullName} 已结束。"); i.Ended = DateTime.Now; i.Latest = false; } if (i.Ended == null) { Log($"准备开始类型 {i.Type.FullName}。"); i.Start(); i.Latest = true; } else { var span = DateTime.Now - i.Ended.Value; if (span.TotalMilliseconds >= Convert.ToDouble(i.Interval)) { Log($"准备开始类型 {i.Type.FullName}。"); i.Start(); i.Latest = true; } } } if (_break && alive < 1) { break; } Thread.Sleep(1000); GC.Collect(); } Log("循环结束,即将退出。"); } private List GetInstances() { var list = new List(); var types = GetTypes(); foreach (var type in types) { var attribute = RuntimeUtility.GetAttribute(type, false); if (attribute == null) continue; var instance = new CronInstance(); instance.Invoker = this; instance.Attribute = attribute; instance.Type = type; list.Add(instance); } return list; } private List GetTypes() { var list = new List(); var assemblies = _assemblies; foreach (var assembly in assemblies) { var types = RuntimeUtility.GetTypes(assembly); foreach (var type in types) { if (!type.IsPublic) continue; if (type.IsAbstract) continue; if (!RuntimeUtility.CanNew(type)) continue; list.Add(type); } } return list; } #endregion #region Static /// 获取或设置日志记录器。 public static Logger Logger { get; set; } /// 在当前线程开始 Cron 调用,可能会阻塞当前线程。可指定 Log 处理程序。 public static CronInvoker Start(Assembly assembly, Action log = null) { var assemblies = new Assembly[] { assembly }; return Start(assemblies); } /// 在当前线程开始 Cron 调用,可能会阻塞当前线程。可指定 Log 处理程序。 public static CronInvoker Start(IEnumerable assemblies, Action log = null) { var instance = new CronInvoker(); instance.LogAction = log; instance.Load(assemblies); instance.Start(); return instance; } #endregion } }