using CCDCount.DLL.Tools; using CCDCount.MODEL.CameraClass; using CCDCount.MODEL.ConfigModel; using CCDCount.MODEL.ShuLiClass; using LogClass; using MvCameraControl; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Remoting.Messaging; using System.Threading; namespace CCDCount.DLL { public class MainThreadClass { #region 变量与实例 Thread SwitchIdentifyImageThread = null; private bool IsSwitch = false; public ShuLiClass shuLiClass = null; CameraClass cameraClass = new CameraClass(); public string ThisCameraDevice = string.Empty; public string ThisCameraSN = string.Empty; public string ThisCamerName = string.Empty; public int ThisCamerNo = -1; //留给主界面的回调函数 public event EventHandler WorkerToFrom; public bool CameraStatic { get { return _CameraStatic; } } private bool _CameraStatic = false; // 返回交换线程状态 public bool CameraRunStatic { get { return IsSwitch; } } public bool IsOpenLoadThread { get { return _IsOpenLoadThread; }} private bool _IsOpenLoadThread = false; public int HistoryActiveNum { get { return shuLiClass.GetHistoryActiveNum(); } } public int OkHistoryNum { get { return shuLiClass.GetOkHistoryNum(); } } public int NgHistoryNum { get { return shuLiClass.GetNgHistoryNum(); } } // 数粒信息发送线程 Thread SendBottLogicMessageThread = null; bool IsSend = false; // Modbus客户端实例 ModbusTcpClient modbusTcpClient = null; // 颗粒结果待发送队列 ConcurrentQueue SendQueue = new ConcurrentQueue(); /// /// 数粒状态计时器 /// Stopwatch stopwatch = Stopwatch.StartNew(); /// /// 数粒状态 /// private bool _ShuLiState = true; public bool ShuLiState { get { return _ShuLiState; } } #endregion #region 公共方法 public void SetModbusClient(ModbusTcpClient modbusTcpClient) { this.modbusTcpClient = modbusTcpClient; if (!this.modbusTcpClient.IsTcpClientConnected()) { LOG.error("ModbusTcpClient Connect Failed!"); } else { StartSendBottLogicMessageThread(); LOG.log("ModbusTcpClient Connect Success!", 6); } } public MainThreadClass(ShuLiConfigClass configClass,CameraConfig CameraConfig) { // 数粒配置文件地址 if (configClass!=null) { // 创建数粒对象(配置文件) shuLiClass = new ShuLiClass(configClass); } else { // 创建数粒对象(默认) shuLiClass = new ShuLiClass(); } _IsOpenLoadThread = CameraConfig.IsOpenLoad; ThisCameraSN = CameraConfig.CameraSNNum; ThisCamerName = CameraConfig.CameraName; ThisCameraDevice = CameraConfig.DeviceName; ThisCamerNo = CameraConfig.CamerNo; } /// /// 开始主线程 /// public bool StartMianThread(CameraConfig DeviceConfig) { bool result = false; // 相机列表 List list = new List(); // 获取相机列表 cameraClass.GetCameraList(out list); if (list.Count == 0) { LOG.error(string.Format("{0}:没有相机", "MainThreadClass-StartMianThread")); // 如果没有相机,则退出 return result; } // 加载相机 // cameraClass.LoadCamereDevice(list.First().DeviceSN); if(!cameraClass.LoadCamereDevice(DeviceConfig)) { LOG.error(string.Format("{0}:相机加载失败", "MainThreadClass-StartMianThread")); return result; } // 取图线程开启 cameraClass.StartCamera(); _CameraStatic = true; // 数据交换线程开启 StartSwitchThread(); // 为数粒算法的识别成功一粒回调函数添加方法 shuLiClass.WorkCompleted += Worker_OneGrainCompleted; // 开启识别线程 shuLiClass.StartIdentifyFuntion(cameraClass.GetCamereImageSize().Width); result = true; return result; } /// /// 开始主线程 /// public bool StartMianThread() { bool result = false; // 相机列表 List list = new List(); // 获取相机列表 cameraClass.GetCameraList(out list); if (list.Count == 0) { // 如果没有相机,则退出 return result; } // 为数粒算法的识别成功一粒回调函数添加方法 shuLiClass.WorkCompleted += Worker_OneGrainCompleted; // 加载相机 if (!cameraClass.LoadCamereDevice(new CameraConfig() { CameraSNNum = list.First().DeviceSN})) return result; _CameraStatic = true; // 取图线程开启 cameraClass.StartCamera(); // 数据交换线程开启 StartSwitchThread(); // 开启识别线程 shuLiClass.StartIdentifyFuntion(cameraClass.GetCamereImageSize().Width); result = true; return result; } /// /// 停止主线程 /// public void StopMianThread() { shuLiClass.WorkCompleted -= Worker_OneGrainCompleted; // 相机取图线程关闭 cameraClass.StopCamera(); // 数据交换线程关闭 StopSwitchThread(); // 数粒识别线程关闭 shuLiClass.StopIdentifyFuntion(); StopSendBottLogicMessageThread(); } public bool ReLoadCamera(string CameraSN) { bool result = false; result = cameraClass.ReLoadCameraDevice(CameraSN); if (result) { CameraConfig ReloadCaonfig = cameraClass.GetConfigValue(); ThisCameraSN = ReloadCaonfig.CameraSNNum; ThisCamerName = ReloadCaonfig.CameraName; ThisCameraDevice = ReloadCaonfig.DeviceName; } return result; } public void DisposeCamera() { cameraClass.StopCamera(); ThisCameraSN = string.Empty; ThisCamerName = string.Empty; ThisCameraDevice = string.Empty; } /// /// 获取显示用的图片数据 /// /// /// public void GetShowImage(int ImageHeight,out Bitmap ImageData) { List RowsShowList = new List(); ActiveObjectClass NewActive = shuLiClass.GetLastActive(); if (NewActive == null) { LOG.log(string.Format("{0}:没有获取到数粒数据", "MainThreadClass-GetShowImage")); ImageData = null; return; } List Data = shuLiClass.GetHistoryActive().Where(o => o.LastSeenLine > NewActive.LastSeenLine - ImageHeight).ToList(); Data.ForEach(o => o.RowsData.ForEach(p => RowsShowList.Add(p))); Bitmap BitmapImage = new Bitmap(NewActive.ImageWidth, ImageHeight); Graphics g = Graphics.FromImage(BitmapImage); Pen redPen = new Pen(Color.Red, 1); List ShowList = RowsShowList.Where(o => o.RowsCol > NewActive.LastSeenLine - BitmapImage.Height).ToList(); RowsShowList.Where(o => o.RowsCol < NewActive.LastSeenLine - BitmapImage.Height).ToList().ForEach(o => RowsShowList.Remove(o)); RowsShowList.Clear(); ShowList.ForEach(o => g.DrawLine(redPen, new Point(o.StartCol, (int)(NewActive.LastSeenLine - o.RowsCol)), new Point(o.EndCol, (int)(NewActive.LastSeenLine - o.RowsCol)))); ShowList.Clear(); ImageData = BitmapImage.Clone() as Bitmap; BitmapImage.Dispose(); //GC.Collect(); } /// /// 获取此刻的Config数据 /// /// public void GetConfigValue(out CameraConfig Camconfig,out ShuLiConfigClass shuLiConfig) { //判断是否加载了相机 if(cameraClass.IsLoadCamera()) //获取已经加载的相机的配置 Camconfig = cameraClass.GetConfigValue(); else //新建一个相机配置 Camconfig = new CameraConfig(); //读取视觉配置 shuLiConfig = shuLiClass.GetConfigValue(); } /// /// 获取相机此刻的Config数据 /// /// public void GetCameraConfig(out CameraConfig CameraConfig) { //判断是否加载了相机 if (cameraClass.IsLoadCamera()) //获取已经加载的相机的配置 CameraConfig = cameraClass.GetConfigValue(); else //新建一个相机配置 CameraConfig = new CameraConfig(); } /// /// 保存所有Config /// public void SaveAllConfig() { shuLiClass.SaveConfig(); } /// /// 获取相机连接状态 /// /// public bool GetCameraConnectStatic() { bool result = false; if(cameraClass != null) result = cameraClass.IsConnectCamera(); return result; } public void Dispose() { //MechanicalControl.Dispose(); } #endregion #region 私有方法 //bool IsFill = false; //bool IsXuanZhuanCloseFaMen = false; /// /// 每数完一粒识别线程执行的事件 /// /// /// private void Worker_OneGrainCompleted(object sender, ActiveObjectEventArgsClass e) { LOG.log("有活跃物体转换为了历史物体,回调事件被触发!", 6); LOG.log(string.Format("图像处理实例中的待识别图像缓存队列长度{0}", shuLiClass.ImageNum), 6); if (e.Actives.Where(o => o.StateCode == 7).Count() > 0) { stopwatch.Restart(); _ShuLiState = false; } else if (stopwatch.ElapsedMilliseconds > 1000) { stopwatch.Stop(); _ShuLiState = true; } //往数组中计数 ushort result = new ushort(); // 事件处理逻辑 foreach (ActiveObjectClass oneActive in e.Actives) { Console.WriteLine(string.Format("输出当前颗粒信息,开始行:{0},结束行:{1},开始时间:{2}结束时间:{3},颗粒状态:{4},通道数:{5}", oneActive.StartLine, oneActive.LastSeenLine, oneActive.StartCheckTime.ToString("O"), oneActive.EndCheckTime.ToString("O"), oneActive.StateCode, oneActive.ChannelNO)); LOG.log(string.Format("输出当前颗粒信息,开始行:{0},结束行:{1},开始时间:{2}结束时间:{3},颗粒状态:{4},通道数:{5}", oneActive.StartLine, oneActive.LastSeenLine, oneActive.StartCheckTime.ToString("O"), oneActive.EndCheckTime.ToString("O"), oneActive.StateCode, oneActive.ChannelNO), 6); if (oneActive.StateCode == 0 && oneActive.ChannelNO != -1) { //单通道合格计数 result |= (ushort)(1 << (oneActive.ChannelNO)); } else { //单通道不合格计数 result |= (ushort)(1 << 8); } } LOG.log("当前待发送队列数量:" + SendQueue.Count, 6); if(IsSend) { SendQueue.Enqueue(result); } } /// /// 对外通知事件 /// private void OnOneGrain(List activeObject) { ActiveObjectEventArgsClass activeObjectEventArgs = new ActiveObjectEventArgsClass(activeObject); // 触发事件 WorkerToFrom?.Invoke(this, activeObjectEventArgs); } #endregion #region 线程方法 /// /// 开启交换线程 /// private void StartSwitchThread() { IsSwitch = true; SwitchIdentifyImageThread = new Thread(SwitchIdentifyImageProcess); SwitchIdentifyImageThread.Start(); } /// /// 关闭交换线程 /// private void StopSwitchThread() { try { // 标志位设为false IsSwitch = false; if (SwitchIdentifyImageThread != null && SwitchIdentifyImageThread.IsAlive) SwitchIdentifyImageThread.Join(); } catch (Exception ex) { LOG.error("Start thread failed!, " + ex.Message); throw; } } /// /// 交换线程 /// private void SwitchIdentifyImageProcess() { IFrameOut IFramedata = null; Stopwatch stopwatch = Stopwatch.StartNew(); stopwatch.Start(); while (IsSwitch) { if (stopwatch.ElapsedMilliseconds > 1000) { Console.WriteLine("交换线程-图像处理实例中的待识别图像缓存队列长度{0}", shuLiClass.ImageNum); GC.Collect(); stopwatch.Restart(); } //Thread.Sleep(5); bool result = cameraClass.GetOnceImage(out IFramedata); if (result) { if (IFramedata == null) continue; shuLiClass.SetOnceIdentifyImageData(IFramedata.Image); } else continue; IFramedata.Dispose(); } stopwatch.Stop(); } /// /// 启动发送消息线程 /// private void StartSendBottLogicMessageThread() { try { //zmcauxClass.OpenZmcauxCard(); timeBeginPeriod(1); // 设置为1ms精度 IsSend = true; SendBottLogicMessageThread = new Thread(SendBottLogicMessageProcess); SendBottLogicMessageThread.Start(); } catch (Exception ex) { LOG.error("Start thread failed!, " + ex.Message); throw; } } /// /// 停止发送消息线程 /// private void StopSendBottLogicMessageThread() { try { // 标志位设为false IsSend = false; if (SendBottLogicMessageThread != null && SendBottLogicMessageThread.IsAlive) SendBottLogicMessageThread.Join(); if (modbusTcpClient != null) modbusTcpClient.Disconnect(); } catch (Exception ex) { LOG.error("Start thread failed!, " + ex.Message); throw; } } /// /// 信息发送线程 /// private void SendBottLogicMessageProcess() { //获取数据 ushort sendMessage = 0; bool AllowTransfer = false; bool TransferDone = false; Stopwatch sw = Stopwatch.StartNew(); while (IsSend) { LOG.log("进入线程", 6); sw.Restart(); sendMessage = new ushort(); //读取装瓶状态 AllowTransfer = false; TransferDone = false; bool[] ReadResult = modbusTcpClient.ReadCoilsRegister(slaveId: 1, startAddress: 11, numRegisters: 2); if (ReadResult == null) { continue; } AllowTransfer = ReadResult[1]; TransferDone = ReadResult[0]; //LOG.log(string.Format("读取值:AllowTransfer[0]:{0},TransferDone[1]:{1}", AllowTransfer, TransferDone), 6); //当允许写入且处于未写入的状态时 if (AllowTransfer && !TransferDone) { if (SendQueue.Count() > 0) { if (!SendQueue.TryDequeue(out sendMessage)) { LOG.error("MainThreadClass-SendBottLogicMessageProcess-SendQueue.TryDequeue failed!"); } } if (sendMessage != 0) { //写入数据 modbusTcpClient.WriteSingleRegister(slaveId: 1, registerAddress: 100, value: sendMessage); modbusTcpClient.WriteCoilsRegister(slaveId: 1, CoilsAddress: 11, values: true); } } sw.Stop(); LOG.log(string.Format("离开线程写入值:sendMessage[1]:{0},此次写值耗时:{1}", sendMessage, sw.Elapsed), 6); Thread.Sleep(1); } } #endregion #region 外部函数 [DllImport("winmm.dll")] static extern uint timeBeginPeriod(uint period); #endregion } }