using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using WCS.Entity; namespace WCS.Core { public abstract class LogicHandler { protected bool Stoped = false; protected string Description { get; private set; } public static List AllObjects = new List(); private static List Handlers = new List(); public static Action DbLog; public LogicHandler() { var attr = this.GetType().GetCustomAttributes(false).OfType().FirstOrDefault(); if (attr != null) Description = attr.Description; else Description = this.GetType().Name; } public abstract void Start(); public virtual bool ParallelRun { get { return false; } } /// /// 数据刷新时触发 /// /// 离上次触发的间隔时间(毫秒) public abstract void Update(double milliseconds); public void Stop() { Stoped = true; } public static void AddManager(LogicHandler handler) { Handlers.Add(handler); } public static void StartAll() { foreach (var h in Handlers) { h.Start(); } var th = new Thread(new ThreadStart(Loop)); th.IsBackground = true; th.Start(); } private static DateTime last = DateTime.Now; private static DateTime last2 = DateTime.Now; private static int logicTimes; public static DateTime Frame { get; private set; } private static void Loop() { var arr = AllObjects.OfType().Where(v => v.ENABLED).SelectMany(v => v.PROTOCOLS) .Where(v => v.ENABLED && v.DB.ENABLED && v.DB.PLC.ENABLED) .GroupBy(v => v.DB).Select(v => v.Key) .ToArray(); while (true) { var dd = DateTime.Now; Frame = DateTime.Now; Parallel.ForEach(arr, db => { try { Ltc.SetChannel("刷新"); db.Ex().DataRefresh(); } catch (Exception ex) { Console.WriteLine("更新" + db.NAME + "数据失败:" + ex.Message); } }); var dbTimes = (DateTime.Now - dd).TotalMilliseconds; // Console.WriteLine("----------"+dd2); var total = (DateTime.Now - last).TotalMilliseconds; var s = (int)(600 - total); if (s > 0) Thread.Sleep(s); total = (DateTime.Now - last).TotalMilliseconds; Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("------刷新DB块数据耗时:" + ((int)dbTimes).ToString().PadRight(4, ' ') + ";业务逻辑耗时:" + ((int)logicTimes).ToString().PadRight(4, ' ') + ";周期总耗时" + ((int)total).ToString().PadRight(4, ' ') + ""); Console.ResetColor(); last = DateTime.Now; //Configs.DoCmds(cmd => //{ // try // { // if (!cmd.ENABLED) // return; // var obj = Device.Find(cmd.DEVICE_CODE).PROTOCOLS.Where(v => v.DB.PROTOCOL == cmd.PROTOCOL).FirstOrDefault(); // //var obj = AllObjects.OfType().Where(v => v.DB.PROTOCOL == cmd.PROTOCOL && v.DEVICE.CODE == cmd.DEVICE_CODE).FirstOrDefault(); // if (obj != null) // { // var proxy = obj.Data() as ProtocolProxyBase; // if (proxy.WCSVersion != cmd.WCSVERSION && cmd.WCSVERSION >= 0) // { // throw new Exception("WCS数据已变更,无法执行CMD。ID:" + cmd.ID); // } // var prop = proxy.GetType().GetProperty(cmd.PROPERTY); // if (prop.PropertyType.IsEnum) // { // var value = Enum.Parse(prop.PropertyType, cmd.VALUE); // proxy.Update(cmd.PROPERTY, value, cmd.UPDATEUSER); // } // else // { // var value = Convert.ChangeType(cmd.VALUE, prop.PropertyType); // proxy.Update(cmd.PROPERTY, value, cmd.UPDATEUSER); // } // } // } // catch (Exception ex) // { // Console.WriteLine(ex.Message); // } //}); Parallel.ForEach(Handlers, m => { var dm = DateTime.Now; try { m.Update(total); } catch (Exception ex) { //Console.WriteLine(ex.GetBaseException().Message); } var dm2 = (DateTime.Now - dm).TotalMilliseconds; //Console.WriteLine(m.GetType().Name + ":" + dm2); }); //foreach (var m in Handlers) //{ // var dm = DateTime.Now; // try // { // m.Update(total); // } // catch (Exception ex) // { // //Console.WriteLine(ex.GetBaseException().Message); // } // var dm2 = (DateTime.Now - dm).TotalMilliseconds; //} Configs.Publish(); logicTimes = (int)(DateTime.Now - last).TotalMilliseconds; } } public static void StopAll() { foreach (var h in Handlers) { try { h.Stop(); } catch { } } } } public abstract class LogicHandler : LogicHandler where T : EntityEx { private string logPath = ""; protected List> Works = new List>(); private IEnumerable _Objects = null; protected IEnumerable Objects { get { if (_Objects == null) { _Objects = AllObjects.OfType().Where(v => SelectDevice(v)).Select(v => Activator.CreateInstance(typeof(T), v)).OfType().ToArray(); } return _Objects.Where(v => v.Entity.ENABLED && v.Entity.PROTOCOLS.All(d => d.ENABLED && d.DB.ENABLED && d.DB.PLC.ENABLED)); } } private bool SelectDevice(WCS_DEVICE dev) { var typenames = typeof(T).GenericTypeArguments.Select(v => v.AssemblyQualifiedName).ToArray(); var res = typenames.All(v => dev.PROTOCOLS.Any(d => d.DB.PROTOCOL == v)); return res; } public LogicHandler() { logPath = @"Log\" + this.Description + @"\"; } public void AddWork(Func condition, Action work, bool parallel = false) { var title = work.Method.Name; var attr = work.Method.GetCustomAttributes(false).OfType().FirstOrDefault(); if (attr != null) title = attr.Description; var arr = Objects.Where(condition).ToArray(); this.Works.Add(new WorkInfo { Work = work, Params = arr, Title = title, Parallel = parallel }); } public void AddWork(IEnumerable arr, Action work, bool parallel = false) { var title = work.Method.Name; var attr = work.Method.GetCustomAttributes(false).OfType().FirstOrDefault(); if (attr != null) title = attr.Description; this.Works.Add(new WorkInfo { Work = work, Params = arr, Title = title, Parallel = parallel }); } public override void Update(double milliseconds) { if (ParallelRun) { Parallel.ForEach(Works, w => { DoWork(w); }); } else { foreach (var w in Works) { DoWork(w); } } } protected virtual void DoWork(WorkInfo work) { if (work.Parallel) { Parallel.ForEach(work.Params, p => { Do(work, p); }); } else { foreach (var p in work.Params) { Do(work, p); } } } protected virtual void Do(WorkInfo wi, T p) { var channel = Description + "." + wi.Title + "." + p.ToString(); try { Ltc.SetChannel(channel); Ltc.Log("开始---------------------------------------"); wi.Work(p); } catch (Exception ex) { Ltc.Log(ex.GetBaseException().Message); Log(wi, p, ex); } finally { Ltc.Log("结束\n"); } } protected virtual void Log(WorkInfo wi, T p, Exception ex) { try { var msg = Description + "--" + wi.Title + "--"; if (p is IProtocol) { msg += (p as IProtocol).PROTOCOL().DEVICE.NAME; } var con = ex.GetBaseException().Message.Split("|"); msg = msg + ":" + con[0]; //Console.WriteLine(msg); DbLog.Invoke(msg, con[1], con[2]); } catch (Exception ex2) { } } private static object lockobj = new object(); protected void Log(string msg) { lock (lockobj) { try { var str = "-----------" + DateTime.Now.ToString("yyyyMMdd HH:mm:ss:fff") + "-----------\r\n"; str += msg; if (!Directory.Exists(logPath)) Directory.CreateDirectory(logPath); var file = logPath + DateTime.Now.ToString("yyyyMMdd") + ".log"; var writer = File.AppendText(file); writer.WriteLine(str); writer.Flush(); writer.Close(); } catch (Exception ex) { } } } /// /// 此方法不会被自动调用,请在Start方法中使用AddWork将其添加至工作队列 /// /// [Description("执行")] protected abstract void Execute(T dev); } public abstract class WorkHandler : LogicHandler { private string logPath = ""; protected List Works = new List(); public WorkHandler() { logPath = @"Log\" + this.Description + @"\"; var arr = Assembly.GetEntryAssembly().GetTypes().Where(v => v.IsSubclassOf(typeof(Work))).Where(v => { var attr = v.GetCustomAttribute(); if (attr == null) return false; return attr.Handler == this.GetType(); }); var works = arr.Select(v => Activator.CreateInstance(v) as Work).Select(v => { var attr = v.GetType().GetCustomAttribute(); return new WorkInfo { Params = v.GetObjs(), Work = v.Execute, Title = attr.Title, Parallel = attr.Parallel }; }).ToArray(); Works.AddRange(works); } public override sealed void Start() { //throw new NotImplementedException(); } public override void Update(double milliseconds) { if (ParallelRun) { Parallel.ForEach(Works, w => { DoWork(w); }); } else { foreach (var w in Works) { DoWork(w); } } } protected virtual void DoWork(WorkInfo work) { if (work.Parallel) { Parallel.ForEach(work.Params, p => { Do(work, p); }); } else { foreach (var p in work.Params) { Do(work, p); } } } protected virtual void Do(WorkInfo wi, object p) { var dt = DateTime.Now; var channel = Description + "." + wi.Title + "." + p.ToString(); try { Ltc.SetChannel(channel); Ltc.Log("开始---------------------------------------"); wi.Work(p); } catch (Exception ex) { Ltc.Log(ex.GetBaseException().Message); Log(wi, p, ex); Configs.UploadException?.Invoke(p.ToString(), ex.GetBaseException().Message); } finally { var dd = (DateTime.Now - dt).TotalMilliseconds; if (dd > 500) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(channel + "耗时" + dd); Console.ResetColor(); } if (dd > 10000) Configs.UploadException?.Invoke(p.ToString(), wi.Title + "执行耗时" + Math.Floor(dd / 1000) + "秒"); Ltc.Log("结束\n"); } } protected virtual void Log(WorkInfo wi, object p, Exception ex) { try { var msg = Description + "--" + wi.Title + "--"; if (p is IProtocol) { msg += (p as IProtocol).PROTOCOL().DEVICE.NAME; } var con = ex.GetBaseException().Message.Split("|"); msg = msg + ":" + con[0]; Console.WriteLine(msg); DbLog.Invoke(msg, con[1], con[2]); } catch (Exception ex2) { } } private static object lockobj = new object(); protected void Log(string msg) { lock (lockobj) { try { var str = "-----------" + DateTime.Now.ToString("yyyyMMdd HH:mm:ss:fff") + "-----------\r\n"; str += msg; if (!Directory.Exists(logPath)) Directory.CreateDirectory(logPath); var file = logPath + DateTime.Now.ToString("yyyyMMdd") + ".log"; var writer = File.AppendText(file); writer.WriteLine(str); writer.Flush(); writer.Close(); } catch (Exception ex) { } } } } public class WorkTitleAttribute : Attribute { public Type Handler { get; set; } public string Title { get; set; } public bool Parallel { get; set; } public WorkTitleAttribute(Type handler, string title, bool parallel = false) { this.Handler = handler; this.Title = title; this.Parallel = parallel; } } public abstract class Work { public abstract IEnumerable GetObjs(); public abstract void Execute(object obj); } public abstract class Work : Work { public override sealed void Execute(object obj) { Do((T)obj); } public override sealed IEnumerable GetObjs() { return InitObjects().OfType().ToArray(); } protected abstract void Do(T obj); protected abstract bool SelectDevice(WCS_DEVICE dev); protected virtual IEnumerable InitObjects() { var arr = Device.Where(v => v.ENABLED) .Where(v => SelectDevice(v)).ToArray(); var res = arr.Select(v => (T)Activator.CreateInstance(typeof(T), v)); return res; } } public abstract class DeviceWork : Work where T : EntityEx { private string[] typenames; public DeviceWork() { typenames = typeof(T).GenericTypeArguments.Select(v => v.AssemblyQualifiedName).ToArray(); } protected abstract override void Do(T obj); protected override sealed IEnumerable InitObjects() { var arr = Device.Where(v => v.ENABLED && v.PROTOCOLS.All(d => d.ENABLED && d.DB.ENABLED && d.DB.PLC.ENABLED)) .Where(v => typenames.All(d => v.PROTOCOLS.Any(e => e.DB.PROTOCOL == d))) .Where(v => SelectDevice(v)).ToArray(); var res = arr.Select(v => Activator.CreateInstance(typeof(T), v) as T); return res; } } }