|
@@ -16,6 +16,7 @@ namespace parkMonitor.server.CoreThread
|
|
|
{
|
|
|
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>();
|
|
@@ -41,6 +42,9 @@ namespace parkMonitor.server.CoreThread
|
|
|
catch (Exception) { fetchStoreRatio = 3; UILogServer.ins.error("未找到停取车比例与计时参数"); }
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 从web线程获得用户指令
|
|
|
+ /// </summary>
|
|
|
private void ReceiveFromWebThread()
|
|
|
{
|
|
|
while (!isClosing)
|
|
@@ -62,7 +66,7 @@ namespace parkMonitor.server.CoreThread
|
|
|
cmd.parkingRecordsID = webMsg.parkingRecordsID;
|
|
|
cmd.TimeRecord = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
webMsg = null;
|
|
|
- UILogServer.ins.info("收到web指令:"+cmd.commandType+"--"+cmd.LicenseNum);
|
|
|
+ UILogServer.ins.info("收到web指令:" + cmd.commandType + "--" + cmd.LicenseNum);
|
|
|
}
|
|
|
//input user command
|
|
|
if (cmd != null)
|
|
@@ -85,102 +89,258 @@ namespace parkMonitor.server.CoreThread
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 队列线程主业务逻辑
|
|
|
+ /// </summary>
|
|
|
private void Run()
|
|
|
{
|
|
|
+ NumberMachineNode temp = null;
|
|
|
while (!isClosing)
|
|
|
{
|
|
|
- Command cmd = null;
|
|
|
- //接收号牌消息
|
|
|
- //update license when it has been used
|
|
|
- if (numMachineHandle != null && (license == null || license.ip == "used" || license.ip == ""))
|
|
|
+ lock (LicenseQueue)
|
|
|
{
|
|
|
- license = ((NumberMachineMessage)numMachineHandle.GetMessage()).aModel;
|
|
|
+ //本地号牌已使用,则接收新的号牌消息
|
|
|
+ if (numMachineHandle != null && !NumMachineNodeValidation(license))
|
|
|
+ {
|
|
|
+ license = ((NumberMachineMessage)numMachineHandle.GetMessage()).aNode;
|
|
|
+ //无重复则入号牌队列,并将号牌机线程获得的Node中ip标记为已使用
|
|
|
+ if (NumMachineNodeValidation(license) && !LicenseQueue.Contains(license))
|
|
|
+ {
|
|
|
+ LicenseQueue.Enqueue((NumberMachineNode)license.Clone());
|
|
|
+ license.ip = "used";
|
|
|
+ //UILogServer.ins.log("已扫描到号牌:" + license.LicenseNum + ",开始排队");
|
|
|
+ Console.WriteLine("已扫描到号牌:" + license.LicenseNum + ",开始排队");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //将已被使用的号牌从号牌队列排除
|
|
|
+ for (int i = 0; i < LicenseQueue.Count; i++)
|
|
|
+ {
|
|
|
+ temp = LicenseQueue.Dequeue();
|
|
|
+ if (temp != null && temp.ip != "used")
|
|
|
+ {
|
|
|
+ LicenseQueue.Enqueue(temp);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
//队列业务逻辑
|
|
|
- //match license number
|
|
|
- for (int i = 0; i < StoreCmdQueue.Count; i++)
|
|
|
+ UserCmdMatch();
|
|
|
+ Scheduling();
|
|
|
+ lock (StoreCmdQueue)
|
|
|
{
|
|
|
- cmd = StoreCmdQueue.Dequeue();
|
|
|
- //指令超时处理
|
|
|
- TimeSpan userTimeSpan = DateTime.Now - DateTime.Parse(cmd.TimeRecord);
|
|
|
- //Console.WriteLine("指令已扫描时间:" + userTimeSpan.TotalSeconds);
|
|
|
- if (userTimeSpan.TotalMinutes >= userTime)
|
|
|
- {
|
|
|
- UILogServer.ins.error("异常:用户指令已存在时间:" + userTimeSpan.TotalSeconds + "秒 ,强制出队");
|
|
|
- //Console.WriteLine("指令已扫描时间:" + userTimeSpan.TotalSeconds);
|
|
|
- //cmd.LicenseNum = "";
|
|
|
- cmd.commandType = 'e';
|
|
|
- ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
- if (StoreCmdQueue.Count != 0)
|
|
|
- cmd = StoreCmdQueue.Dequeue();
|
|
|
- else
|
|
|
- break;
|
|
|
- }
|
|
|
- if (license != null && cmd.LicenseNum.Equals(license.LicenseNum))
|
|
|
+ UserCmdTimeOut();
|
|
|
+ }
|
|
|
+ lock (LicenseQueue)
|
|
|
+ {
|
|
|
+ LicTimeOut();
|
|
|
+ }
|
|
|
+ Thread.Sleep(200);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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("异常:用户指令已存在时间:" + userTimeSpan.TotalSeconds + "秒 ,强制出队");
|
|
|
+ //Console.WriteLine("异常:用户指令已存在时间:" + userTimeSpan.TotalSeconds + "秒 ,强制出队");
|
|
|
+ //cmd.LicenseNum = "";
|
|
|
+ cmd.commandType = 'e';
|
|
|
+ lock (ValidStoreCmdQueue)
|
|
|
{
|
|
|
- //匹配上,时间定为号牌机获取号牌时间
|
|
|
- cmd.TimeRecord = license.TimeRecord;
|
|
|
ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
- license.ip = "used";
|
|
|
- break;
|
|
|
}
|
|
|
+ if (StoreCmdQueue.Count != 0)
|
|
|
+ cmd = StoreCmdQueue.Dequeue();
|
|
|
else
|
|
|
- {
|
|
|
- StoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
- }
|
|
|
+ break;
|
|
|
}
|
|
|
- //号牌超时处理
|
|
|
- if (license != null && license.TimeRecord != "")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 号牌超时处理
|
|
|
+ /// </summary>
|
|
|
+ private void LicTimeOut()
|
|
|
+ {
|
|
|
+ foreach (NumberMachineNode n in LicenseQueue)
|
|
|
+ {
|
|
|
+ if (NumMachineNodeValidation(n))
|
|
|
{
|
|
|
- TimeSpan licTimeSpan = DateTime.Now - DateTime.Parse(license.TimeRecord);
|
|
|
- //测试,超过5分钟自动出队
|
|
|
- //Console.WriteLine("号牌已扫描时间:"+ licTimeSpan.TotalSeconds);
|
|
|
- if (license.ip!="used" && license.ip != "" && licTimeSpan.TotalMinutes >= licenseTime)
|
|
|
+ //计算时间差,超过5分钟自动出队(?处理方式待讨论),并将该Node标记为已使用,等待统一处理
|
|
|
+ TimeSpan licTimeSpan = DateTime.Now - DateTime.Parse(n.TimeRecord);
|
|
|
+ if (licTimeSpan.TotalMinutes >= licenseTime)
|
|
|
{
|
|
|
UILogServer.ins.error("异常:号牌已扫描时间:" + licTimeSpan.TotalSeconds + "秒 ,强制出队");
|
|
|
- //Console.WriteLine("号牌已扫描时间:" + licTimeSpan.TotalSeconds);
|
|
|
- cmd = new Command();
|
|
|
- cmd.ip = license.ip;
|
|
|
+ //Console.WriteLine("异常:号牌已扫描时间:" + licTimeSpan.TotalSeconds + "秒 ,强制出队");
|
|
|
+ Command cmd = new Command();
|
|
|
+ cmd.ip = n.ip;
|
|
|
cmd.commandType = 's';
|
|
|
- cmd.LicenseNum = license.LicenseNum;
|
|
|
+ cmd.LicenseNum = n.LicenseNum;
|
|
|
cmd.userID = "";
|
|
|
cmd.garageID = 0;
|
|
|
cmd.parkingRecordsID = 0;
|
|
|
- cmd.TimeRecord = license.TimeRecord;
|
|
|
- ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
+ cmd.TimeRecord = n.TimeRecord;
|
|
|
+ lock (ValidStoreCmdQueue)
|
|
|
+ {
|
|
|
+ ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
+ }
|
|
|
//numMachineHandle.SetMessage((AbstractMessage)cmd.Clone());
|
|
|
- license.ip = "used";
|
|
|
+ n.ip = "used";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 停车匹配,一轮中从停车指令队列取一个,遍历号牌队列;之后反之,以号牌遍历停车指令队列
|
|
|
+ /// 匹配上则入合法指令队列,并标记号牌队列相应元素为已使用
|
|
|
+ /// </summary>
|
|
|
+ private void UserCmdMatch()
|
|
|
+ {
|
|
|
+ Command cmd = null;
|
|
|
+ NumberMachineNode num = null;
|
|
|
+
|
|
|
+ //以单用户指令遍历号牌队列
|
|
|
+ lock (StoreCmdQueue)
|
|
|
+ {
|
|
|
+ if (StoreCmdQueue.Count != 0)
|
|
|
+ {
|
|
|
+ cmd = StoreCmdQueue.Dequeue();
|
|
|
+ num = new NumberMachineNode();
|
|
|
+ lock (LicenseQueue)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < LicenseQueue.Count; i++)
|
|
|
+ {
|
|
|
+ num = LicenseQueue.Dequeue();
|
|
|
+ //匹配成功
|
|
|
+ if (cmd.LicenseNum.Equals(num.LicenseNum))
|
|
|
+ {
|
|
|
+ cmd.TimeRecord = num.TimeRecord;
|
|
|
+ ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
+ cmd = null;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LicenseQueue.Enqueue((NumberMachineNode)num.Clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (cmd != null)
|
|
|
+ {
|
|
|
+ StoreCmdQueue.Enqueue(cmd);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- //scheduling algorithm
|
|
|
- int fetch = fetchStoreRatio;
|
|
|
+ //以单号牌遍历停车指令队列
|
|
|
+ lock (LicenseQueue)
|
|
|
+ {
|
|
|
+ if (LicenseQueue.Count != 0)
|
|
|
+ {
|
|
|
+ num = LicenseQueue.Dequeue();
|
|
|
+ cmd = new Command();
|
|
|
+ lock (StoreCmdQueue)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < StoreCmdQueue.Count; i++)
|
|
|
+ {
|
|
|
+ cmd = StoreCmdQueue.Dequeue();
|
|
|
+ //匹配成功
|
|
|
+ if (num.LicenseNum.Equals(cmd.LicenseNum))
|
|
|
+ {
|
|
|
+ cmd.TimeRecord = num.TimeRecord;
|
|
|
+ ValidStoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
+ cmd = null;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ StoreCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (cmd != null)
|
|
|
+ {
|
|
|
+ LicenseQueue.Enqueue(num);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <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+" 的车辆,开始排队");
|
|
|
+ //UILogServer.ins.info("任务:取出号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
|
|
|
}
|
|
|
+ }
|
|
|
+ lock (ValidStoreCmdQueue)
|
|
|
+ {
|
|
|
if (ValidStoreCmdQueue.Count != 0)
|
|
|
{
|
|
|
cmd = ValidStoreCmdQueue.Dequeue();
|
|
|
ExecutableCmdQueue.Enqueue((Command)cmd.Clone());
|
|
|
- UILogServer.ins.info("任务:存入号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
|
|
|
+ //UILogServer.ins.info("任务:存入号牌为 " + cmd.LicenseNum + " 的车辆,开始排队");
|
|
|
}
|
|
|
- Thread.Sleep(1000);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //公有方法
|
|
|
- //please reset the licenseNum to "" after using
|
|
|
+ /// <summary>
|
|
|
+ /// 获取一个停取车指令
|
|
|
+ /// </summary>
|
|
|
public AbstractMessage GetMessage()
|
|
|
{
|
|
|
- return (Command)ExecutableCmdQueue.Dequeue();
|
|
|
+ lock (ExecutableCmdQueue)
|
|
|
+ {
|
|
|
+ return (Command)ExecutableCmdQueue.Dequeue();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 由核心线程调用,传入已存车完成需要标记的号牌
|
|
|
+ /// </summary>
|
|
|
+ /// <example>
|
|
|
+ /// NumberMachineMessage numberMachineMessage = new NumberMachineMessage();
|
|
|
+ /// numberMachineMessage.aNode = new NumberMachineNode();
|
|
|
+ /// numberMachineMessage.aNode.ip = "";
|
|
|
+ /// numberMachineMessage.aNode.LicenseNum = "the number plate that has been used";
|
|
|
+ /// QueueingHandle.SetMessage(numberMachineMessage);
|
|
|
+ /// </example>
|
|
|
+ /// <param name="message"></param>
|
|
|
public void SetMessage(AbstractMessage message)
|
|
|
{
|
|
|
- //there's no need to do any thing
|
|
|
+ if (numMachineHandle != null)
|
|
|
+ {
|
|
|
+ numMachineHandle.SetMessage(message);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public void Start()
|