123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using parkMonitor.entity;
- using parkMonitor.model;
- using parkMonitor.server;
- using System.Configuration;
- using parkMonitor.tools;
- using parkMonitor.server.uiLogServer;
- namespace parkMonitor.server.CoreThread
- {
- /// <summary>
- /// 队列线程,处理号牌与停取车指令业务逻辑
- /// </summary>
- public class QueuingThread : IEquipments
- {
- Queue<NumberMachineNode> LicenseQueue = new Queue<NumberMachineNode>();
- Queue<Command> StoreCmdQueue = new Queue<Command>();
- Queue<Command> ValidStoreCmdQueue = new Queue<Command>();
- Queue<Command> FetchCmdQueue = new Queue<Command>();
- BlockingQueue ExecutableCmdQueue = new BlockingQueue();
- int fetchStoreRatio, licenseTime, userTime;
- bool isClosing = false;
- IEquipments webHandle = null;
- IEquipments numMachineHandle = null;
- NumberMachineNode license;
- MessageUTF8 webMsg;
- /// <summary>
- /// 队列构造函数
- /// </summary>
- public QueuingThread()
- {
- webHandle = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.Web);
- numMachineHandle = EquipmentSimpleFactory.ins.FindEquipment(EquipmentName.NumMachine);
- try
- {
- fetchStoreRatio = Int32.Parse(ConfigurationManager.AppSettings.Get("fetch_store_ratio"));
- licenseTime = Int32.Parse(ConfigurationManager.AppSettings.Get("licenseTime"));
- userTime = Int32.Parse(ConfigurationManager.AppSettings.Get("userTime"));
- }
- catch (Exception) { fetchStoreRatio = 3; UILogServer.ins.error("未找到停取车比例与计时参数"); }
- }
- /// <summary>
- /// 从web线程获得用户指令
- /// </summary>
- private void ReceiveFromWebThread()
- {
- while (!isClosing)
- {
- Command cmd = null;
- //接收web消息
- if (webHandle != null)
- {
- try
- {
- webMsg = (MessageUTF8)((MessageUTF8)webHandle.GetMessage()).Clone();
- }
- catch (Exception) { UILogServer.ins.error("用户指令异常"); }
- }
- //get useful data from webMsg and assign it to output data structure
- if (webMsg != null)
- {
- cmd = new Command();
- cmd.commandType = webMsg.cmd;
- cmd.LicenseNum = webMsg.context;
- cmd.userID = webMsg.sender;
- cmd.garageID = webMsg.garageID;
- cmd.parkingRecordsID = webMsg.parkingRecordsID;
- cmd.TimeRecord = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- webMsg = null;
- }
- //input user command
- if (cmd != null)
- {
- if (cmd.commandType.Equals('f'))
- {
- lock (FetchCmdQueue)
- {
- FetchCmdQueue.Enqueue((Command)cmd.Clone());
- }
- UILogServer.ins.info("收到web取车指令:" + cmd.LicenseNum);
- }
- //停车先遍历
- else if (cmd.commandType.Equals('s'))
- {
- UserCmdMatch(cmd);
- UILogServer.ins.info("收到web停车指令:" + cmd.LicenseNum);
- }
- else
- {
- Console.WriteLine("invalid user command.");
- UILogServer.ins.error("从web收到无法识别的用户指令,并非停取车");
- }
- }
- Thread.Sleep(500);
- }
- }
- /// <summary>
- /// 队列线程主业务逻辑
- /// </summary>
- private void Run()
- {
- NumberMachineNode temp = null;
- while (!isClosing)
- {
- lock (LicenseQueue)
- {
- //本地号牌已使用,则接收新的号牌消息
- if (numMachineHandle != null && !NumMachineNodeValidation(license))
- {
- license = ((NumberMachineMessage)numMachineHandle.GetMessage()).aNode;
- //无重复则匹配指令,匹配失败则入号牌队列,并将号牌机线程获得的Node中ip标记为已使用
- if (NumMachineNodeValidation(license) && !LicenseQueue.Contains(license))
- {
- UILogServer.ins.info("已扫描到号牌:" + license.LicenseNum + ",匹配中");
- Console.WriteLine("已扫描到号牌:" + license.LicenseNum + ",匹配中");
- //先匹配指令
- NumMatch(ref license);
- }
- }
- //将已被使用的号牌从号牌队列排除
- for (int i = 0; i < LicenseQueue.Count; i++)
- {
- temp = LicenseQueue.Dequeue();
- if (temp != null && temp.ip != "used")
- {
- LicenseQueue.Enqueue(temp);
- }
- }
- }
- //队列业务逻辑
- //UserCmdMatch();
- Scheduling();
- lock (StoreCmdQueue)
- {
- UserCmdTimeOut();
- }
- lock (LicenseQueue)
- {
- NumTimeOut();
- }
- Thread.Sleep(500);
- }
- }
- /// <summary>
- /// 号牌节点有效性验证
- /// </summary>
- /// <param name="node"></param>
- /// <returns></returns>
- private bool NumMachineNodeValidation(NumberMachineNode node)
- {
- return (node != null && node.ip != null && node.ip != "" && node.ip != "used") ? true : false;
- }
- /// <summary>
- /// 停车指令超时处理
- /// </summary>
- private void UserCmdTimeOut()
- {
- Command cmd = null;
- for (int i = 0; i < StoreCmdQueue.Count; i++)
- {
- cmd = StoreCmdQueue.Dequeue();
- //指令超时处理
- TimeSpan userTimeSpan = DateTime.Now - DateTime.Parse(cmd.TimeRecord);
- //Console.WriteLine("指令已扫描时间:" + userTimeSpan.TotalSeconds);
- if (userTimeSpan.TotalMinutes >= userTime)
- {
- UILogServer.ins.error("异常:用户指令 "+ cmd.LicenseNum+ " 已存在超过" + userTimeSpan.TotalMinutes + "分钟 ,强制出队");
- //cmd.LicenseNum = "";
- cmd.commandType = 'e';
- lock (ValidStoreCmdQueue)
- {
- ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
- }
- if (StoreCmdQueue.Count != 0)
- cmd = StoreCmdQueue.Dequeue();
- else
- break;
- }
- //未超时则归队
- else
- {
- StoreCmdQueue.Enqueue((Command)cmd.Clone());
- }
- }
- }
- /// <summary>
- /// 号牌超时处理
- /// </summary>
- private void NumTimeOut()
- {
- for (int i = 0; i < LicenseQueue.Count; i++)
- {
- NumberMachineNode node = LicenseQueue.Dequeue();
- if (NumMachineNodeValidation(node))
- {
- //计算时间差,超过5分钟自动出队(?处理方式待讨论),并将该Node标记为已使用,等待统一处理
- TimeSpan licTimeSpan = DateTime.Now - DateTime.Parse(node.TimeRecord);
- if (licTimeSpan.TotalMinutes >= licenseTime)
- {
- //异常号牌不再入队,而是界面提示管理员,并让号牌机线程
- UILogServer.ins.error("异常:号牌 " + node.LicenseNum + " 已扫描超过" + licTimeSpan.TotalMinutes + "分钟 ,强制出队");
- //停车完成,将相应车牌复位
- NumberMachineMessage numberMachineMessage = new NumberMachineMessage();
- numberMachineMessage.aNode = new NumberMachineNode();
- numberMachineMessage.aNode.ip = "";
- numberMachineMessage.aNode.LicenseNum = node.LicenseNum;
- numMachineHandle.SetMessage(numberMachineMessage);
- node.ip = "used";
- }
- }
- LicenseQueue.Enqueue(node);
- }
- }
- /// <summary>
- /// 单用户指令匹配号牌队列
- /// </summary>
- private void UserCmdMatch(Command cmd)
- {
- lock (StoreCmdQueue)
- {
- NumberMachineNode num = null;
- bool matched = false;
- num = new NumberMachineNode();
- lock (LicenseQueue)
- {
- for (int i = 0; i < LicenseQueue.Count; i++)
- {
- num = LicenseQueue.Dequeue();
- //匹配成功
- if (NumMachineNodeValidation(num) && cmd.LicenseNum.Equals(num.LicenseNum))
- {
- cmd.TimeRecord = num.TimeRecord;
- cmd.ip = num.ip;
- cmd.id = num.id;
- ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
- matched = true;
- break;
- }
- else
- {
- LicenseQueue.Enqueue((NumberMachineNode)num.Clone());
- }
- }
- }
- if (!matched)
- {
- StoreCmdQueue.Enqueue((Command)cmd.Clone());
- }
- }
- }
- /// <summary>
- /// 单号牌匹配用户指令队列
- /// </summary>
- private void NumMatch(ref NumberMachineNode license)
- {
- Command cmd = new Command();
- bool matched = false;
- lock (StoreCmdQueue)
- {
- for (int i = 0; NumMachineNodeValidation(license) && i < StoreCmdQueue.Count; i++)
- {
- cmd = StoreCmdQueue.Dequeue();
- //匹配成功
- if (license.LicenseNum.Equals(cmd.LicenseNum))
- {
- cmd.TimeRecord = license.TimeRecord;
- cmd.ip = license.ip;
- cmd.id = license.id;
- ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
- matched = true;
- break;
- }
- else
- {
- StoreCmdQueue.Enqueue((Command)cmd.Clone());
- }
- }
- }
- lock (LicenseQueue)
- {
- if (!matched)
- {
- LicenseQueue.Enqueue((NumberMachineNode)license.Clone());
- }
- }
- license.ip = "used";
- }
- /// <summary>
- /// 停取车调度,控制停取车比例,可多取一停,也可一取一停
- /// </summary>
- private void Scheduling()
- {
- //scheduling algorithm
- int fetch = fetchStoreRatio;
- Command cmd = null;
- lock (FetchCmdQueue)
- {
- while (FetchCmdQueue.Count != 0 && fetch-- > 0)
- {
- cmd = FetchCmdQueue.Dequeue();
- ExecutableCmdQueue.Enqueue((Command)cmd.Clone());
- UILogServer.ins.info("任务:取出号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
- }
- }
- lock (ValidStoreCmdQueue)
- {
- if (ValidStoreCmdQueue.Count != 0)
- {
- cmd = ValidStoreCmdQueue.Dequeue();
- ExecutableCmdQueue.Enqueue((Command)cmd.Clone());
- UILogServer.ins.info("任务:存入号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
- }
- }
- }
- /// <summary>
- /// 获取一个停取车指令
- /// </summary>
- public AbstractMessage GetMessage()
- {
- lock (ExecutableCmdQueue)
- {
- return (Command)ExecutableCmdQueue.Dequeue();
- }
- }
- /// <summary>
- /// 功能一:由核心线程调用,传入已存车完成需要标记的号牌
- /// 功能二:添加手动停取车指令
- /// </summary>
- public void SetMessage(AbstractMessage message)
- {
- //号牌机重置消息
- if (message.GetType().Equals(typeof(NumberMachineMessage)))
- {
- if (numMachineHandle != null)
- {
- numMachineHandle.SetMessage(message);
- }
- }
- //手动停取车指令
- else if (message.GetType().Equals(typeof(Command)))
- {
- Command command = (Command)message;
- //command.garageID = 0;
- //command.parkingRecordsID = 0;
- command.TimeRecord = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
- //input user command
- if (command != null)
- {
- if (command.returnedCount > 0)
- {
- if (command.commandType.Equals('s'))
- {
- lock (ValidStoreCmdQueue)
- {
- ValidStoreCmdQueue.Enqueue((Command)command.Clone());
- }
- UILogServer.ins.info("收到退回的停车指令:" + command.LicenseNum);
- }
- else if(command.commandType.Equals('f')){
- lock (FetchCmdQueue)
- {
- FetchCmdQueue.Enqueue((Command)command.Clone());
- }
- UILogServer.ins.info("收到退回的取车指令:" + command.LicenseNum);
- }
- }
- else
- {
- if (command.commandType.Equals('f'))
- {
- lock (FetchCmdQueue)
- {
- FetchCmdQueue.Enqueue((Command)command.Clone());
- }
- UILogServer.ins.info("收到手动的取车指令:" + command.LicenseNum);
- }
- else if (command.commandType.Equals('s'))
- {
- UserCmdMatch(command);
- UILogServer.ins.info("收到手动的停车指令:" + command.LicenseNum);
- }
- else
- {
- Console.WriteLine("invalid user command.");
- UILogServer.ins.error("收到无法识别的手动用户指令");
- }
- }
- }
- }
- }
- public void Start()
- {
- license = null;
- webMsg = null;
- Task.Factory.StartNew(() =>
- {
- ReceiveFromWebThread();
- });
- Task.Factory.StartNew(() =>
- {
- Run();
- });
- }
- public void Stop()
- {
- isClosing = true;
- }
- }
- }
|