11 changed files with 124 additions and 331 deletions
@ -1,95 +0,0 @@ |
|||
using Apewer; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using System.Threading; |
|||
|
|||
namespace Apewer.Web |
|||
{ |
|||
|
|||
internal sealed class CronInstance |
|||
{ |
|||
|
|||
internal bool _latest = false; |
|||
internal Type _type = null; |
|||
internal Logger _logger = null; |
|||
internal Class<DateTime> _ended = null; |
|||
internal CronAttribute _attribute = null; |
|||
internal CronInvoker _invoker = null; |
|||
|
|||
private Thread _thread = null; |
|||
private bool _break = false; |
|||
|
|||
#region properties
|
|||
|
|||
// 当前线程正在运行。
|
|||
public bool Alive { get => GetAlive(); } |
|||
|
|||
// 再次启动 Cron 的时间间隔。
|
|||
public int Interval { get => GetInterval(); } |
|||
|
|||
// 最后一次检查的 Alive 值。
|
|||
public bool Latest { get => _latest; } |
|||
|
|||
// Cron 类型。
|
|||
public Type Type { get => _type; } |
|||
|
|||
public CronAttribute Attribute { get => _attribute; } |
|||
|
|||
public Class<DateTime> Ended { get => _ended; } |
|||
|
|||
#endregion
|
|||
|
|||
public CronInstance() |
|||
{ |
|||
_thread = new Thread(Listen); |
|||
_thread.IsBackground = true; |
|||
} |
|||
|
|||
/// <summary>打断循环。</summary>
|
|||
public void Break() => _break = true; |
|||
|
|||
/// <summary>启动线程执行任务。</summary>
|
|||
public void Start() |
|||
{ |
|||
if (Alive) return; |
|||
_thread = new Thread(Listen); |
|||
_thread.IsBackground = true; |
|||
_thread.Start(); |
|||
} |
|||
|
|||
int GetInterval() |
|||
{ |
|||
if (_attribute == null) _attribute = new CronAttribute(); |
|||
return _attribute.Interval; |
|||
} |
|||
|
|||
bool GetAlive() |
|||
{ |
|||
if (_thread == null) return false; |
|||
if (_thread.IsAlive != true) return false; |
|||
if (_thread.ThreadState != ThreadState.Running) return false; |
|||
return true; |
|||
} |
|||
|
|||
void Listen() |
|||
{ |
|||
if (Type == null) return; |
|||
var instance = null as object; |
|||
try |
|||
{ |
|||
instance = Activator.CreateInstance(Type); |
|||
} |
|||
catch (Exception exception) |
|||
{ |
|||
Log(Type.FullName, exception.GetType().FullName, exception.Message); |
|||
} |
|||
RuntimeUtility.Dispose(instance); |
|||
_thread = null; |
|||
} |
|||
|
|||
void Log(params object[] content) => _logger.Text(Type.FullName, content); |
|||
|
|||
} |
|||
|
|||
} |
@ -1,189 +0,0 @@ |
|||
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
|
|||
|
|||
} |
|||
|
|||
} |
Loading…
Reference in new issue