//private Dictionary<string, Conveyor> dicConveyor = new Dictionary<string, Conveyor>(); //void Conveyor_OnDataChanged(object sender, DataChangedEventArgs e) //{ // try // { // if (e.State == null) // return; // string txt = e.ItemName.Split('_')[0]; // Conveyor conveyor = GetConveyorByID(txt); // conveyor.value = e.State.ToString(); // conveyor.ID = txt; // Conveyors.ConveyorInfo(conveyor); // } // catch (Exception ex) // { // MCP.Logger.Error("输送线监控界面中Conveyor_OnDataChanged出现异常" + ex.Message); // } //} //private Conveyor GetConveyorByID(string ID) //{ // Conveyor conveyor = null; // if (dicConveyor.ContainsKey(ID)) // { // conveyor = dicConveyor[ID]; // } // else // { // conveyor = new Conveyor(); // conveyor.ID = ID; // dicConveyor.Add(ID, conveyor); // } // return conveyor; //} //void Monitor_OnConveyor(ConveyorEventArgs args) //{ // if (InvokeRequired) // { // BeginInvoke(new ConveyorEventHandler(Monitor_OnConveyor), args); // } // else // { // try // { // Conveyor conveyor = args.conveyor; // Button btn = GetButton(conveyor.ID); // if (btn == null) // return; // if (conveyor.value == "0" && conveyor.ID.IndexOf("Conveyor") >= 0) // btn.Text = ""; // else if (conveyor.value == "0" && conveyor.ID.IndexOf("UpDown") >= 0) // btn.Text = "◎"; // else if (conveyor.value == "0" && conveyor.ID.IndexOf("Move") >= 0) // btn.Text = ""; // else if (conveyor.value == "1" && conveyor.ID.IndexOf("Conveyor") >= 0) //有货未转 // btn.Text = "■"; // else if (conveyor.value == "1" && conveyor.ID.IndexOf("UpDown") >= 0) //有货未转 // btn.Text = "●"; // else if (conveyor.value == "1" && conveyor.ID.IndexOf("Move") >= 0) // btn.Text = btn.Tag.ToString(); // else if (conveyor.value == "2") //无货未转 // btn.Text = ""; // else if (conveyor.value == "3") //转 // btn.Text = btn.Tag.ToString(); // else if (conveyor.value == "4") // btn.BackColor = Color.Red; // else // btn.Text = ""; // } // catch (Exception ex) // { // MCP.Logger.Error("监控界面中Monitor_OnConveyor出现异常" + ex.Message); // } // } //} #endregion #region 堆垛机监控 void Crane_OnDataChanged(object sender, DataChangedEventArgs e) { if (e.State == null) { return; } string CraneNo = e.ServerName.Replace("CraneServer", ""); GetCrane(CraneNo); if (e.ItemName.IndexOf("Mode") >= 0) { dicCrane[CraneNo].Mode = int.Parse(e.State.ToString()); } else if (e.ItemName.IndexOf("State") >= 0) { dicCrane[CraneNo].State = int.Parse(e.State.ToString()); } else if (e.ItemName.IndexOf("Fork") >= 0) { dicCrane[CraneNo].Fork = int.Parse(e.State.ToString()); } else if (e.ItemName.IndexOf("TaskNo") >= 0) { dicCrane[CraneNo].TaskNo = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(e.States)); } else if (e.ItemName.IndexOf("AlarmCode") >= 0) { dicCrane[CraneNo].AlarmCode = int.Parse(e.State.ToString()); } else if (e.ItemName.IndexOf("Station") >= 0) { dicCrane[CraneNo].Station = e.States; } Cranes.CraneInfo(dicCrane[CraneNo]); }
void CranePLC_OnDataChanged(object sender, DataChangedEventArgs e) { if (e.State == null) return; string CraneNo = e.ServerName.Replace("CranePLC", ""); GetCrane(CraneNo); if (e.ItemName.IndexOf("Mode") >= 0) dicCrane[CraneNo].Mode = int.Parse(e.State.ToString()); else if (e.ItemName.IndexOf("State1") >= 0) dicCrane[CraneNo].State1 = int.Parse(e.State.ToString()); else if (e.ItemName.IndexOf("Fork1") >= 0) dicCrane[CraneNo].Fork1 = int.Parse(e.State.ToString()); else if (e.ItemName.IndexOf("TaskNo1") >= 0) dicCrane[CraneNo].TaskNo1 = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(e.States)); else if (e.ItemName.IndexOf("State2") >= 0) dicCrane[CraneNo].State2 = int.Parse(e.State.ToString()); else if (e.ItemName.IndexOf("Fork2") >= 0) dicCrane[CraneNo].Fork2 = int.Parse(e.State.ToString()); else if (e.ItemName.IndexOf("TaskNo2") >= 0) dicCrane[CraneNo].TaskNo2 = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(e.States)); else if (e.ItemName.IndexOf("AlarmCode") >= 0) dicCrane[CraneNo].AlarmCode = int.Parse(e.State.ToString()); else if (e.ItemName.IndexOf("Station") >= 0) dicCrane[CraneNo].Station = e.States; Cranes.CraneInfo(dicCrane[CraneNo]); }
void Crane_OnDataChanged(object sender, DataChangedEventArgs e) { if (e.State == null) { return; } string CraneNo = e.ServerName.Substring(5, 2); GetCrane(CraneNo); if (e.ItemName.IndexOf("Status") >= 0) { dicCrane[CraneNo].Status = int.Parse(e.States[4].ToString()); dicCrane[CraneNo].Row = int.Parse(e.States[5].ToString()); } else if (e.ItemName.IndexOf("WorkMode") >= 0) { dicCrane[CraneNo].Mode = int.Parse(e.States[1].ToString()); dicCrane[CraneNo].AlarmCode = int.Parse(e.States[2].ToString()); dicCrane[CraneNo].Load = int.Parse(e.States[3].ToString()); dicCrane[CraneNo].Column = int.Parse(e.States[4].ToString()); dicCrane[CraneNo].Layer = int.Parse(e.States[5].ToString()); dicCrane[CraneNo].ForkStatus = int.Parse(e.States[6].ToString()); } else if (e.ItemName.IndexOf("TaskNo") >= 0) { dicCrane[CraneNo].TaskNo = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(e.States)); } if (e.ItemName.IndexOf("STB") >= 0) { dicCrane[CraneNo].STB = int.Parse(e.States[0].ToString()); dicCrane[CraneNo].ACK = int.Parse(e.States[1].ToString()); } Cranes.CraneInfo(dicCrane[CraneNo]); }
private void tmCraneWorker1(object sender, System.Timers.ElapsedEventArgs e) { try { tmCrane1.Stop(); int[] location = new int[2]; string serviceName = "CranePLC1"; object[] obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CraneLocation")); for (int j = 0; j < obj.Length; j++) { location[j] = Convert.ToInt16(obj[j]) - 48; } int[] craneInfo = new int[6]; obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CraneInfo")); for (int j = 0; j < obj.Length; j++) { craneInfo[j] = Convert.ToInt16(obj[j]) - 48; } string palletCode = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CranePalletCode"))); obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CraneTaskNo")); string plcTaskNo = Util.ConvertStringChar.BytesToString(obj); obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CraneSpeed")); Crane crane = new Crane(); crane.CraneNo = 1; crane.Column = location[0]; crane.Height = location[1]; crane.ForkStatus = craneInfo[1]; crane.Action = craneInfo[2]; crane.TaskType = craneInfo[3]; crane.ErrCode = craneInfo[4]; crane.PalletCode = palletCode; crane.TaskNo = plcTaskNo; crane.WalkCode = int.Parse(obj[3].ToString()); crane.UpDownCode = int.Parse(obj[4].ToString()); Cranes.CraneInfo(crane); } catch (Exception ex) { Logger.Error(ex.Message); } finally { tmCrane1.Start(); } }
private void tmCraneWorker1(object sender, System.Timers.ElapsedEventArgs e) { try { tmCrane1.Stop(); string binary = Convert.ToString(255, 2).PadLeft(8, '0'); string serviceName = "CranePLC1"; string plcTaskNo = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "CraneTaskNo")).ToString(); if (plcTaskNo == "0") { plcTaskNo = ""; } string craneMode = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "CraneMode")).ToString(); string craneFork = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "CraneFork")).ToString(); object[] obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CraneAlarmCode")); Crane crane = new Crane(); crane.CraneNo = 1; crane.Row = int.Parse(obj[4].ToString()); crane.Column = int.Parse(obj[2].ToString()); crane.Height = int.Parse(obj[3].ToString()); crane.ForkStatus = int.Parse(craneFork); crane.Action = int.Parse(craneMode); crane.TaskType = int.Parse(obj[1].ToString()); crane.ErrCode = int.Parse(obj[0].ToString()); crane.PalletCode = ""; crane.TaskNo = plcTaskNo; Cranes.CraneInfo(crane); } catch (Exception ex) { Logger.Error(ex.Message); } finally { tmCrane1.Start(); } }
private void tmCraneWorker2(object sender, System.Timers.ElapsedEventArgs e) { try { tmCrane2.Stop(); string serviceName = "CranePLC2"; string plcTaskNo = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "CraneTaskNo")).ToString(); string craneMode = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "CraneMode")).ToString(); string craneFork = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "CraneFork")).ToString(); object[] obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "CraneAlarmCode")); Crane crane2 = new Crane(); crane2.CraneNo = 2; crane2.Row = int.Parse(obj[4].ToString()); crane2.Column = int.Parse(obj[2].ToString()); crane2.Height = int.Parse(obj[3].ToString()); crane2.ForkStatus = int.Parse(craneFork); crane2.Action = int.Parse(craneMode); crane2.TaskType = int.Parse(obj[1].ToString()); crane2.ErrCode = int.Parse(obj[0].ToString()); crane2.PalletCode = ""; crane2.TaskNo = plcTaskNo; Cranes.CraneInfo(crane2); } catch (Exception ex) { Logger.Error("2号堆垛机监控故障:" + ex.Message); } finally { tmCrane2.Start(); } }
void CraneServer_OnDataChanged(object sender, DataChangedEventArgs e) { try { if (e.State == null) { return; } PLC plc = new PLC(); string[] txt = e.ItemName.Split('_'); plc.ID = txt[0]; plc.PicName = "picCrane"; plc.ShowPic = "1"; plc.TextName = "txt" + txt[1]; if (e.ItemName.IndexOf("TaskNo") >= 0) { string TaskNo = Util.ConvertStringChar.BytesToString(e.States); plc.Text = TaskNo; plc.TaskType = ""; plc.TextTypeName = "txtTaskType"; if (TaskNo.Length > 0) { DataTable dtTask = bll.FillDataTable("WCS.SelectWCSTask", new DataParameter[] { new DataParameter("{0}", string.Format("TASKID='{0}'", TaskNo)) }); if (dtTask.Rows.Count > 0) { if (dtTask.Rows[0]["TASKTYPE"].ToString() == "IB") { plc.TaskType = "入库"; } else { plc.TaskType = "出库"; } } } } else if (e.ItemName.IndexOf("PalletCode") >= 0) { plc.Text = Util.ConvertStringChar.BytesToString(e.States); } else if (e.ItemName.IndexOf("CraneAction") >= 0) { int Action = int.Parse(ObjectUtil.GetObject(e.States).ToString()); plc.Text = dicCraneAction[Action]; } else if (e.ItemName.IndexOf("Column") >= 0) { string Ocolumn = ObjectUtil.GetObject(e.States).ToString(); plc.Text = Ocolumn; Crane crane = new Crane(); crane.CraneNo = int.Parse(txt[0]); int column = 0; if (Ocolumn != "") { column = int.Parse(Ocolumn); } crane.Column = column; Cranes.CraneInfo(crane); } else if (e.ItemName.IndexOf("Row") >= 0) { int Row = int.Parse(ObjectUtil.GetObject(e.States).ToString()); if (Row >= 2) { Row = Row - 1; } plc.Text = Row.ToString(); } else { string strErrorNo = ObjectUtil.GetObject(e.States).ToString(); if (strErrorNo != "0") { DataRow[] drs = dtCraneError.Select(string.Format("warncode='{0}'", strErrorNo)); if (drs.Length > 0) { plc.Text = drs[0]["WARNDESC"].ToString(); } else { plc.Text = "未知错误!"; } plc.TextName = "txtErrorDesc"; plc.IsErr = "1"; plc.ErrCode = strErrorNo; plc.TextErrName = "txtErrorNo"; } else { plc.Text = ""; plc.TextName = "txtErrorDesc"; plc.IsErr = "0"; plc.ErrCode = strErrorNo; plc.TextErrName = "txtErrorNo"; } } PLCS.PLCInfo(plc); } catch (Exception ex) { MCP.Logger.Error("监控界面CraneServer_OnDataChanged中出现异常" + ex.Message); } }
private void GetCraneInfo(int CraneNo) { try { string serviceName = "CranePLC" + CraneNo; Crane crane = new Crane(); crane.CraneNo = CraneNo; int[] location = new int[2]; string plcPalletCode = ""; string plcTaskNo = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "s_I_task_no"))); if (plcTaskNo != "") { plcPalletCode = Util.ConvertStringChar.BytesToString(ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "s_I_pallet_code"))); } crane.TaskNo = plcTaskNo; crane.PalletCode = plcPalletCode; if (plcTaskNo.Length > 0) { int n_column1 = (int)ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "n_column1")); int n_column2 = (int)ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "n_column2")); if (n_column1 == 0) { crane.TaskType = 1;//入库 } else { crane.TaskType = 2;//出库 } } else { crane.TaskType = 0; } crane.Action = (int)ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "nState"));//Action object[] obj = ObjectUtil.GetObjects(Context.ProcessDispatcher.WriteToService(serviceName, "nTravelPos")); //列层 for (int j = 0; j < obj.Length; j++) { location[j] = Convert.ToInt16(obj[j].ToString()); } crane.Column = location[0]; crane.Height = location[1]; string b_I_Alarm = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "b_I_Alarm")).ToString(); string b_I_Warning = ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "b_I_Warning")).ToString(); crane.ErrCode = (int)ObjectUtil.GetObject(Context.ProcessDispatcher.WriteToService(serviceName, "nAlarmCode")); if (crane.ErrCode == 504 || crane.ErrCode == 505) { DataTable dtErr = bll.FillDataTable("WCS.SelectWmsSend", new DataParameter[] { new DataParameter("{0}", string.Format("TASKID='{0}'", plcTaskNo)) }); if (dtErr.Rows.Count > 0) { string Taskstatus = dtErr.Rows[0]["TASKSTATUS"].ToString(); if (Taskstatus == "4") { bll.ExecNonQueryTran("WCS.SPCancelTask", new DataParameter[] { new DataParameter("VTASKNO", plcTaskNo) }); Logger.Info(dicCraneTaskType[crane.TaskType] + "任务:" + plcTaskNo + " 托盘编号:" + dtErr.Rows[0]["PALLETID"].ToString() + "任务废弃!"); if (crane.ErrCode == 504)//空取异常 { //取消堆垛机当前任务 Context.ProcessDispatcher.WriteToService(serviceName, "b_O_Cancel_Task", true); sbyte[] taskNo = new sbyte[12]; Util.ConvertStringChar.stringToBytes("", 12).CopyTo(taskNo, 0); Context.ProcessDispatcher.WriteToService(serviceName, "s_I_task_no", taskNo); } else //crane.ErrCode == 505,重入异常 { DataTable dtTask = bll.FillDataTable("WCS.SelectWmsTask", new DataParameter[] { new DataParameter("{0}", string.Format("PALLETID='{0}' AND TASKSTATUS='0' AND ASRSID='{1}'", plcPalletCode, CraneNo)) }); if (dtTask.Rows.Count > 0) { string PalletCode = dtTask.Rows[0]["PALLETID"].ToString(); string TaskNo = dtTask.Rows[0]["TASKID"].ToString(); sbyte[] staskNo = new sbyte[12]; Util.ConvertStringChar.stringToBytes(TaskNo, 12).CopyTo(staskNo, 0); sbyte[] spalletCode = new sbyte[8]; Util.ConvertStringChar.stringToBytes(PalletCode, 8).CopyTo(spalletCode, 0); string DLocation = dtTask.Rows[0]["DLOCATION"].ToString(); Int16 ToShelf = Int16.Parse(DLocation.Split('-')[0]); Int16 ToColumn = Int16.Parse(DLocation.Split('-')[1]); Int16 ToRow = Int16.Parse(DLocation.Split('-')[2]); Context.ProcessDispatcher.WriteToService(serviceName, "n_shelf1", Util.ConvertStringChar.GetBytes(0)); Context.ProcessDispatcher.WriteToService(serviceName, "n_column1", Util.ConvertStringChar.GetBytes(0)); Context.ProcessDispatcher.WriteToService(serviceName, "n_Row1", Util.ConvertStringChar.GetBytes(0)); Context.ProcessDispatcher.WriteToService(serviceName, "n_shelf2", Util.ConvertStringChar.GetBytes(ToShelf)); Context.ProcessDispatcher.WriteToService(serviceName, "n_column2", Util.ConvertStringChar.GetBytes(ToColumn)); Context.ProcessDispatcher.WriteToService(serviceName, "n_Row2", Util.ConvertStringChar.GetBytes(ToRow)); Context.ProcessDispatcher.WriteToService(serviceName, "s_O_task_no", staskNo); Context.ProcessDispatcher.WriteToService(serviceName, "s_O_pallet_code", spalletCode); if (Context.ProcessDispatcher.WriteToService(serviceName, "b_O_New_Task", true)) { //更新WCSTask状态为3 bll.ExecNonQuery("WCS.UpdateWCSTaskState", new DataParameter[] { new DataParameter("{0}", 3), new DataParameter("{1}", TaskNo) }); Logger.Info("入库任务:" + TaskNo + " 托盘编号:" + PalletCode + " 位:" + DLocation + " 已下发给" + CraneNo + "堆垛机"); } else { Logger.Error("入库任务:" + TaskNo + " 托盘编号:" + PalletCode + " 无法写入堆垛机" + CraneNo); } } else { Logger.Error(dicCraneTaskType[crane.TaskType] + "任务:" + plcTaskNo + " WMS未处理该异常:"); } } } } else { Logger.Info(dicCraneTaskType[crane.TaskType] + "任务:" + plcTaskNo + " WCS未处理该异常:"); } } Cranes.CraneInfo(crane); } catch (Exception ex) { Logger.Error("监控界面,GetCraneInfo出现异常:" + ex.Message); } }
private void tmCraneWorker(object sender, System.Timers.ElapsedEventArgs e) { try { tmCrane.Stop(); for (int i = 1; i <= 5; i++) { TextBox txt = GetTextBox("txtColumn", i); if (txt != null) { Crane crane = new Crane(); crane.CraneNo = i; int column = 0; if (txt.Text != "") { column = int.Parse(txt.Text); } crane.Column = column; Cranes.CraneInfo(crane); } txt = GetTextBox("txtErrorNo", i); if (txt != null) { if (txt.Text.Length == 0) { continue; } int ErrCode = int.Parse(txt.Text); if (ErrCode == 0) { continue; } //string[] d = new string[2]; //d[0] = i.ToString(); //d[1] = GetTextBox("txtErrorDesc", i).Text; //Context.ProcessDispatcher.WriteToProcess("LEDProcess", "Error", d);//LED显示 if (ErrCode == 506 || ErrCode == 505) { string serviceName = "CranePLC" + i; string plcTaskNo = GetTextBox("txtTaskNo", i).Text; string plcPalletCode = GetTextBox("txtPalletCode", i).Text; DataTable dtErr = bll.FillDataTable("WCS.SelectWmsSend", new DataParameter[] { new DataParameter("{0}", string.Format("TASKID='{0}'", plcTaskNo)) }); if (dtErr.Rows.Count > 0) { string Taskstatus = dtErr.Rows[0]["TASKSTATUS"].ToString(); if (Taskstatus == "4") { bll.ExecNonQueryTran("WCS.SPCancelTask", new DataParameter[] { new DataParameter("VTASKNO", plcTaskNo) }); Logger.Info("任务:" + plcTaskNo + " 托盘编号:" + dtErr.Rows[0]["PALLETID"].ToString() + "任务取消!"); if (ErrCode == 506)//空取异常 { //取消堆垛机当前任务 Context.ProcessDispatcher.WriteToService(serviceName, "CancelTask", true); sbyte[] taskNo = new sbyte[20]; Util.ConvertStringChar.stringToBytes("", 20).CopyTo(taskNo, 0); Context.ProcessDispatcher.WriteToService(serviceName, "ClearTaskNo", taskNo); } else //crane.ErrCode == 505,重入异常 { if (GetTextBox("txtTaskType", i).Text == "出库") { continue; } DataTable dtTask = bll.FillDataTable("WCS.SelectWmsTask", new DataParameter[] { new DataParameter("{0}", string.Format("PALLETID='{0}' AND TASKSTATUS='0' AND ASRSID='{1}'", plcPalletCode, i)) }); if (dtTask.Rows.Count > 0) { string TaskNo = dtTask.Rows[0]["TASKID"].ToString(); sbyte[] staskNo = new sbyte[20]; Util.ConvertStringChar.stringToBytes(TaskNo, 12).CopyTo(staskNo, 0); Util.ConvertStringChar.stringToBytes(plcPalletCode, 8).CopyTo(staskNo, 12); string strDLocation = dtTask.Rows[0]["DLOCATION"].ToString(); int[] Location = new int[6]; Location[0] = 0; Location[1] = 0; Location[2] = 0; Location[3] = int.Parse(strDLocation.Split('-')[0]); Location[4] = int.Parse(strDLocation.Split('-')[1]); int ToRow = int.Parse(strDLocation.Split('-')[2]); if (ToRow > 1) { ToRow += 1; } Location[5] = ToRow; Context.ProcessDispatcher.WriteToService(serviceName, "Address", Location); Context.ProcessDispatcher.WriteToService(serviceName, "WriteTask", staskNo); if (Context.ProcessDispatcher.WriteToService(serviceName, "WriteFinish", true)) { bll.ExecNonQueryTran("WCS.SPReciveWmsTask", new DataParameter[] { new DataParameter("VTASKNO", TaskNo) }); //更新WCSTask状态为3 bll.ExecNonQuery("WCS.UpdateWCSTaskState", new DataParameter[] { new DataParameter("{0}", 3), new DataParameter("{1}", TaskNo) }); Logger.Info("入库任务:" + TaskNo + " 托盘编号:" + plcPalletCode + " 位:" + strDLocation + " 已下发给" + i + "堆垛机"); } else { Logger.Error("入库任务:" + TaskNo + " 托盘编号:" + plcPalletCode + " 无法写入堆垛机" + i); } } } } } } } } } catch (Exception ex) { Logger.Error("监控界面中tmCraneWorker出现异常:" + ex.Message); } finally { tmCrane.Start(); } }