using ProjectManagementSystem.Common.Models.Crms; using ProjectManagementSystem.Common.Extenions; using ProjectManagementSystem.Common.Logger; using ProjectManagementSystem.Common.Service; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ProjectManagementSystem.Common.Core { public class TaskBehavior { private static TaskBehavior m_instance; private static ConcurrentDictionary tempLog = new ConcurrentDictionary(); public static ConcurrentDictionary BehaviorDict { get; set; } = new ConcurrentDictionary(); public static ConcurrentDictionary PmsBehaviorLoopDict { get; set; } = new ConcurrentDictionary(); public static TaskBehavior Instance { get { if (m_instance == null) { m_instance = new TaskBehavior(); if (!m_instance.Initialize()) { m_instance = null; } } return m_instance; } } private TaskBehavior() { } public static void Log(TaskData taskData, StepData stepData, string log) { bool result = tempLog.TryGetValue(taskData.TaskID, out string templog) ? templog == log : false; if (result) return; tempLog.AddOrUpdate(taskData.TaskID, log, (key, vaule) => log); string strLog = $"{taskData.TaskID} Step{taskData.CurrentStepID} {stepData.PmsBehavior} {stepData.AgvBehavior} {taskData.Carrier}# {stepData.WareHouseID} {log}"; CLog.Instance.GetAgvLog(taskData.Carrier).WriteInfo(strLog); } public static void RemoveTempLog(string taskId) { if (string.IsNullOrEmpty(taskId)) return; tempLog.TryRemove(taskId, out string _); } public static string GetTempLog(string taskId) { if (string.IsNullOrEmpty(taskId)) return null; return tempLog.TryGetValue(taskId, out string log) ? log : null; } private bool Initialize() { try { Task.Factory.StartNew(UserThread, TaskCreationOptions.LongRunning); return true; } catch (Exception ex) { CLog.Instance.SystemLog.WriteException("TaskBehavior Initialize", ex); } return false; } private void LogDebug(RequestPmsTaskInfo info, string log) { CLog.Instance.GetAgvLog(info.agvId).WriteDebug($"{info.TaskId} Step__ {info.PmsBehavior} {info.agvId}# {log}"); } private void ProcessPmsBehavior() { DateTime start = DateTime.Now; var dataDict = Crms.PmsApi.GetPmsBehavior(); if (dataDict == null || dataDict.Count == 0) return; var taskDataList = Crms.PmsApi.GetTaskDataList(); if (taskDataList == null || taskDataList.Count == 0) return; Parallel.ForEach(dataDict.Values, data => { try { if (!BehaviorDict.TryGetValue(data.PmsBehavior, out var behaviorV2)) { LogDebug(data, "行为码未注册"); return; } //获取任务数据 var taskData = taskDataList.FirstOrDefault(d => d.TaskID == data.TaskId && d.Carrier == data.agvId); if (taskData == null) { LogDebug(data, "查找当前任务失败"); return; } var stepData = taskData.GetCurrentStepInfo(); if (stepData == null) { LogDebug(data, "获取当前任务StepData失败"); return; } if (stepData.PmsBehavior != data.PmsBehavior) { LogDebug(data, $"PMS行为码不匹配 当前任务Step{taskData.CurrentStepID} {stepData.PmsBehavior}"); return; } var taskApiTimeSpan = (DateTime.Now - start).TotalMilliseconds; //执行PMS行为码 DateTime start3 = DateTime.Now; bool result = behaviorV2.TaskBookOperator(taskData, stepData); var operatorTimeSpan = (DateTime.Now - start3).TotalMilliseconds; //上报PMS行为码 if (result) { bool setResult = Crms.PmsApi.SetPmsBehaviorFinish(data.TaskId, taskData.Carrier, data.PmsBehavior); var totalTimeSpan = (DateTime.Now - start).TotalMilliseconds; CLog.Instance.GetAgvLog(taskData.Carrier).WriteDebug($"{taskData.TaskID} Step{taskData.CurrentStepID} {stepData.PmsBehavior} {stepData.AgvBehavior} {taskData.Carrier}# {stepData.WareHouseID}" + $" PMS行为码完成上报{setResult.ToChineseString()} 耗时: {taskApiTimeSpan:F1}ms {operatorTimeSpan:F1}ms 总耗时:{totalTimeSpan:F1}ms"); } } catch (Exception ex) { CLog.Instance.SystemLog.WriteExceptionCaller(ex); } }); } private void ProcessPmsBehaviorTask() { //独立线程执行 var dataDict = Crms.PmsApi.GetPmsBehavior(); if (dataDict == null || dataDict.Count == 0) return; var dataDictValues = dataDict.Values; foreach (var item in dataDictValues) { bool isContainsKey = PmsBehaviorLoopDict.TryGetValue(item.agvId, out var tempLoop); var loop = isContainsKey ? tempLoop : new PmsBehaviorLoop(); if (!loop.IsStart) { loop.BehavoirInfo = item; loop.Start(); } if (!isContainsKey) { PmsBehaviorLoopDict.AddOrUpdate(item.agvId, loop, (key, value) => loop); } } } private void UserThread() { CLog.Instance.SystemLog.WriteDebug($"TaskBehavior已启动"); while (true) { try { ProcessPmsBehaviorTask(); } catch (Exception ex) { CLog.Instance.SystemLog.WriteException("TaskBehavior", ex); Thread.Sleep(5000); } Thread.Sleep(100); } } } public class PmsBehaviorLoop { private int loopCount; private DateTime loopStartTime; public bool IsStart { get; set; } public RequestPmsTaskInfo BehavoirInfo { get; set; } public PmsBehaviorLoop() { } public void Start() { loopCount = 0; loopStartTime = DateTime.Now; IsStart = true; Task.Factory.StartNew(UserThread); } private bool Process() { DateTime start = DateTime.Now; var dataDict = Crms.PmsApi.GetPmsBehavior(); if (dataDict == null) { LogDebug("获取所有PMS行为码失败"); return true; } if (dataDict.Count == 0) { LogDebug("获取所有PMS行为码数量为0"); return true; } if (!dataDict.TryGetValue(BehavoirInfo.agvId, out var find)) { LogDebug("获取当前小车PMS行为码失败"); return true; } if (find.TaskId != BehavoirInfo.TaskId) { LogDebug("检查当前小车PMS行为码 TaskId 不匹配"); return true; } if (find.PmsBehavior != BehavoirInfo.PmsBehavior) { LogDebug("检查当前小车PMS行为码 PmsBehavior 不匹配"); return true; } //获取任务数据 var taskData = Crms.PmsApi.GetTaskData(BehavoirInfo.TaskId); if (taskData == null) { LogDebug("获取当前任务失败"); return true; } var stepData = taskData.GetCurrentStepInfo(); if (stepData == null) { LogDebug("获取当前任务StepData失败"); return true; } if (stepData.PmsBehavior != BehavoirInfo.PmsBehavior) { LogDebug($"PMS行为码不匹配 当前任务Step{taskData.CurrentStepID} {stepData.PmsBehavior}"); return loopCount >= 3; } var taskApiTimeSpan = (DateTime.Now - start).TotalMilliseconds; //执行PMS行为码 DateTime start3 = DateTime.Now; if (!TaskBehavior.BehaviorDict.TryGetValue(BehavoirInfo.PmsBehavior, out var behaviorV2)) { TaskBehavior.Log(taskData, stepData, "行为码未注册"); return false; } bool result = behaviorV2.TaskBookOperator(taskData, stepData); var operatorTimeSpan = (DateTime.Now - start3).TotalMilliseconds; //上报PMS行为码 if (result) { bool setResult = Crms.PmsApi.SetPmsBehaviorFinish(BehavoirInfo.TaskId, taskData.Carrier, BehavoirInfo.PmsBehavior); var totalTimeSpan = (DateTime.Now - start).TotalMilliseconds; var totalLoopTimeSpan = (DateTime.Now - loopStartTime).TotalMilliseconds; var avgLoopTimeSpan = totalLoopTimeSpan / loopCount; CLog.Instance.GetAgvLog(taskData.Carrier).WriteDebug($"{taskData.TaskID} Step{taskData.CurrentStepID} {stepData.PmsBehavior} {stepData.AgvBehavior} {taskData.Carrier}# {stepData.WareHouseID}" + $" PMS行为码完成上报{setResult.ToChineseString()} 耗时:{totalTimeSpan:F1}ms [{taskApiTimeSpan:F1}ms {operatorTimeSpan:F1}ms] 统计:{totalLoopTimeSpan:F1}ms/{loopCount}={avgLoopTimeSpan:F1}ms"); return setResult; } return false; } private void LogDebug(string log) { CLog.Instance.GetAgvLog(BehavoirInfo.agvId).WriteDebug($"{BehavoirInfo.TaskId} Step__ {BehavoirInfo.PmsBehavior} {BehavoirInfo.agvId}# T{loopCount} {log}"); } private void UserThread() { LogDebug("PmsBehaviorLoop已启动"); while (IsStart) { loopCount++; bool processResult = false; try { processResult = Process(); if (processResult) { TaskBehavior.RemoveTempLog(BehavoirInfo.TaskId); } } catch (Exception ex) { CLog.Instance.SystemLog.WriteException("PmsBehaviorLoop", ex); Thread.Sleep(5000); //抛异常退出循环 processResult = true; } if (processResult) { break; } Thread.Sleep(100); } LogDebug("PmsBehaviorLoop已退出"); IsStart = false; } } public abstract class BaseTaskBookBehaviorV2 { public string Name { get; set; } public int Behavior { get; set; } public string Remark { get; set; } public BaseTaskBookBehaviorV2(int behavior, string remark) { Behavior = behavior; Remark = remark; TaskBehavior.BehaviorDict.AddOrUpdate(Behavior, this, (key, value) => this); } public abstract bool TaskBookOperator(TaskData taskData, StepData stepData); public void Log(TaskData taskData, StepData stepData, string log) { TaskBehavior.Log(taskData, stepData, log); } public void LogException(Exception ex) { CLog.Instance.TaskLog.WriteException("TaskBookBehavior", ex); } } }