using Apewer; using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Threading; namespace Apewer.Web { /// Cron 调度器。 internal sealed class CronInvoker { #region Instance private List _assemblies = null; private List _instances = null; private bool _break = false; private Logger _logger = null; /// 获取或设置日志记录器。 public Logger Logger { get { return _logger; } set { _logger = value; } } private void Log(object content) => _logger?.Text("Cron", 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(); break; } // 当前线程正在活动。 if (i.Alive) { i._latest = true; continue; } // 记录 Cron 结束时间,根据结束时间判断再次启动 Cron。 if (i.Latest) { Log($"{i.Type.FullName} Ended"); i._ended = new Class(DateTime.Now); i._latest = false; } if (i.Ended == null) { Log($"{i.Type.FullName} Beginning"); i.Start(); i._latest = true; } else { var span = DateTime.Now - i.Ended.Value; if (span.TotalMilliseconds >= Convert.ToDouble(i.Interval)) { Log($"{i.Type.FullName} Beginning"); i.Start(); i._latest = true; } } } if (_break && alive < 1) { break; } Thread.Sleep(500); 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; instance._logger = Logger; 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 // 在当前线程开始 Cron 调用 。 public static CronInvoker Start(IEnumerable assemblies = null, Logger logger = null) { var instance = new CronInvoker(); instance.Logger = logger; instance.Load(assemblies ?? AppDomain.CurrentDomain.GetAssemblies()); instance.Start(); return instance; } #endregion } }