using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace WCS.Core { public abstract class SystemBase: DescriptionClass { public World World { get; private set; } public SystemBase() { var attr = this.GetType().GetCustomAttribute(); if (attr != null) { var wt = attr.WorldType; this.World = World.Worlds.Where(v => v.GetType() == wt).First(); } } public abstract List GetObjects(); public abstract void Update(List list); } public abstract class SystemBase : SystemBase { public List Objects { get; set; } /// /// 对所有Objects并行循环执行Do /// protected abstract bool ParallelDo { get; } /// /// 保存日志到文件 /// protected abstract bool SaveLogsToFile { get; } public SystemBase() { Objects = Create();//.Select(v=>Activator.CreateInstance(typeof(T),v)).OfType().ToList(); } public override void Update(List list) { var logs = new List(); if (ParallelDo) { Parallel.ForEach(Objects, new ParallelOptions { MaxDegreeOfParallelism = 256 }, obj => { var sw= new Stopwatch(); sw.Start(); InvokeDo(obj); sw.Stop(); list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); //var log = Ltc.GetLogStr(); logs.AddSafe(Ltc.GetLogInfo()); }); } else { foreach (var obj in Objects) { var sw = new Stopwatch(); sw.Start(); InvokeDo(obj); sw.Stop(); list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); //var log = Ltc.GetLogStr(); logs.AddSafe(Ltc.GetLogInfo()); } } if (SaveLogsToFile) { //var arr = logs.GroupBy(v => v.Channel).Select(v => new LogInfo { Channel = v.Key, Level = v.Max(d => d.Level), Type = v.Any(d => d.Type == ErrorType.Unkown) ? ErrorType.Unkown : ErrorType.Kown, Message = "\n"+string.Join('\n', v.Select(d => d.Message)) }).ToArray(); Configs.OnLog?.Invoke(logs); } } void InvokeDo(T obj) { var channel = new Channel { World = World.Description, Stage = "DoLogics", System = Description, Item = obj.ToString() }; try { Ltc.SetChannel(channel); Ltc.Log("开始", LogLevel.Low, ErrorType.Kown); Do(obj); } catch (KnownException ex) { Ltc.Log(ex.Message, ex.Level, ErrorType.Kown); } catch (Exception ex) { //Console.WriteLine($"{channel}:\n{ex.GetBaseException().Message}"); Ltc.Log(ex.GetBaseException().Message, LogLevel.High, ErrorType.Unkown); World.OnError(channel, ex); } finally { Ltc.Log("结束", LogLevel.Low, ErrorType.Kown); Ltc.Publish(this.World); } } public abstract List Create(); public abstract void Do(T obj); public override List GetObjects() { return Objects.OfType().ToList(); } } public abstract class DeviceSystem : SystemBase where T : EntityEx { public override List Create() { var types = typeof(T).GetGenericArguments(); var list= World.Devices.Where(v => types.All(d => v.HasProtocol(d))) .Where(v => Select(v)) .Select(v => Activator.CreateInstance(typeof(T), v)).OfType().ToList();//此时才实例化Protocol return list; } /// /// 筛选出需要实例化Protocol的Device /// /// /// public abstract bool Select(Device dev); //public abstract List CreateDevices(); } public abstract class ServiceSystem : SystemBase { ConcurrentQueue>> Actions = new ConcurrentQueue>>(); public TR Invoke(T obj) { var flag = false; TR result = default(TR); Actions.Enqueue(list => { var sw = new Stopwatch(); sw.Start(); try { result = InvokeDo(obj); } finally { sw.Stop(); list.AddSafe(new WorkTimes { Key = $"{obj?.ToString()}", Total = sw.ElapsedMilliseconds }); flag = true; } }); SpinWait.SpinUntil(() => flag); return result; } protected abstract TR Do(T obj); public override List GetObjects() { return new List(); } public override void Update(List list) { var logs = new List(); while (Actions.TryDequeue(out var act)) { act(list); logs.AddSafe(Ltc.GetLogInfo()); } if (logs.Count > 0) { //var arr = logs.GroupBy(v => v.Channel).Select(v => new LogInfo { Channel = v.Key, Level = v.Max(d => d.Level), Type = v.Any(d => d.Type == ErrorType.Unkown) ? ErrorType.Unkown : ErrorType.Kown, Message = "\n" + string.Join('\n', v.Select(d => d.Message)) }).ToArray(); Configs.OnLog?.Invoke(logs); } } TR InvokeDo(T obj) { var channel = new Channel { World = World.Description, Stage = "DoLogics", System = Description, Item = obj.ToString() }; try { Ltc.SetChannel(channel); Ltc.Log("开始", LogLevel.Low, ErrorType.Kown); return Do(obj); } catch (KnownException ex) { Ltc.Log(ex.Message, ex.Level, ErrorType.Kown); throw; } catch (Exception ex) { //Console.WriteLine($"{channel}:\n{ex.GetBaseException().Message}"); Ltc.Log(ex.GetBaseException().Message, LogLevel.High, ErrorType.Unkown); throw; } finally { Ltc.Log("结束", LogLevel.Low, ErrorType.Kown); Ltc.Publish(this.World); } } } }