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