You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
using Apewer; using System; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Threading;
namespace Apewer.Web {
/// <summary>Cron 调度器。</summary>
internal sealed class CronInvoker {
#region Instance
private List<Assembly> _assemblies = null; private List<CronInstance> _instances = null; private bool _break = false; private Logger _logger = null;
/// <summary>获取或设置日志记录器。</summary>
public Logger Logger { get { return _logger; } set { _logger = value; } }
private void Log(object content) => _logger?.Text("Cron", content);
/// <summary>加载程序集。</summary>
public void Load(IEnumerable<Assembly> assemblies) { Log("开始加载程序集。"); if (_assemblies == null) _assemblies = new List<Assembly>(); 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} 个程序集。"); }
/// <summary>通知打断循环,所有 Cron 执行结束后退出。</summary>
public void Break() => _break = true;
/// <summary>开始 Cron 调用。</summary>
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>(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<CronInstance> GetInstances() { var list = new List<CronInstance>();
var types = GetTypes(); foreach (var type in types) { var attribute = RuntimeUtility.GetAttribute<CronAttribute>(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<Type> GetTypes() { var list = new List<Type>();
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<Assembly> assemblies = null, Logger logger = null) { var instance = new CronInvoker(); instance.Logger = logger; instance.Load(assemblies ?? AppDomain.CurrentDomain.GetAssemblies()); instance.Start(); return instance; }
#endregion
}
}
|