halcon窗体连续拍照并处理结果,几分钟后整个程序界面失去响应。
在任务管理器中会提示程序已经失去响应。
这种问题多半跟跨线程调用有关系。也就是说,处理图像的线程想在halcon窗体内显示结果,但是halcon控件是另一个界面线程中的控件。
例如下面一段程序就是halcon进行图片处理并且显示结果。
其中 m_HWCtrl.InvokeRequired 这个如果为true,则表示调用控件m_HWCtrl的线程是另一个线程在调用,而非拥控件所在的界面线程在调用。
你只需要把实现代码写在else部分即可。
if (m_HWCtrl.InvokeRequired) { Func<bool> fun = weldCheckTopMethod; return (bool)m_HWCtrl.Invoke(fun, new object[] { }); } else { //这里写m_HWCtrl控件的功能代码。 }
private bool weldCheckTopMethod() { int x = 1200, y = 200; var halcon = new visionFunClass(); var winHandle = m_HWCtrl.HalconWindow; try { if (m_HWCtrl == null) return false; if (!m_HWCtrl.CurrentImage.IsInitialized()) return false; if (m_HWCtrl.InvokeRequired) { Func<bool> fun = weldCheckTopMethod; return (bool)m_HWCtrl.Invoke(fun, new object[] { }); } else { //return true; var hwinObj = m_HWCtrl; weldCheckTopResult = false; var list1 = work.gConfig.visionUpROI.explainCSVRow().ConvertAll(s => double.Parse(s)); weldCheck.work.weldCheckParam param = new weldCheck.work.weldCheckParam() { hwin = hwinObj, ptNums = work.gConfig.visionUpPtnums, radDnLimit = work.gConfig.visionUpPtRadLimitDn, radUpLimit = work.gConfig.visionUpPtRadLimitUp, threshold = work.gConfig.visionUpThreshold, roiX1 = list1[0], roiY1 = list1[1], roiX2 = list1[2], roiY2 = list1[3], selectShapeMin=work.gConfig.visionSelectShapeMinTop, selectShapeMax=work.gConfig.visionSelectShapeMaxTop }; var lineAryTmp = new List<Linef>(); int ptnum = 0; bool okng = false; try { okng = halcon.checkTop(param, out lineAryTmp, out ptnum); } catch(Exception ex) { halcon.writeMsg(winHandle, string.Format("错误: {0}", ex.Message), x + 370, y, 9, vFunBaseMethod.setColorEnum.red); } double distanceA = 0, distanceB = 0; if (lineAryTmp!=null && lineAryTmp.Count >= 2) { halcon.dispLines(winHandle, lineAryTmp[0]); halcon.dispLines(winHandle, lineAryTmp[1]); } lineAry[work.lineNameEnum.焊点位置A].FindTargetObj(); lineAry[work.lineNameEnum.焊点位置B].FindTargetObj(); if (lineAryTmp!=null && lineAryTmp.Count >= 2) { distanceA = DistanceLineToLine( lineAry[work.lineNameEnum.焊点位置A].TargetObj, lineAryTmp[0]); distanceA = VxTransTableToWorld(new Pointf(0, distanceA)).y; distanceB = DistanceLineToLine( lineAry[work.lineNameEnum.焊点位置B].TargetObj, lineAryTmp[1]); distanceB = VxTransTableToWorld(new Pointf(0, distanceB)).y; } bool r1 = distanceA < work.gWorkSetting.weldPtPosADnlimit || distanceA > work.gWorkSetting.weldPtPosAUplimit; bool r2= distanceB < work.gWorkSetting.weldPtPosBDnlimit || distanceB > work.gWorkSetting.weldPtPosBUplimit; if (work.gConfig.visionIgnoreSizeAB) r1 = true; bool r3 = ptnum>=work.gConfig.visionUpPtnums; if ((okng && !r1 && !r2 && r3) || work.gConfig.isPassWeldCheckRes) { halcon.writeMsg(winHandle, "OK", x - 230, y , 24, vFunBaseMethod.setColorEnum.green); halcon.writeMsg(winHandle, string.Format("焊点数量: {0}", ptnum), x, y, 12, vFunBaseMethod.setColorEnum.green); halcon.writeMsg(winHandle, string.Format("焊点位置A: {0}", distanceA), x + 130, y, 12, vFunBaseMethod.setColorEnum.green); halcon.writeMsg(winHandle, string.Format("焊点位置B: {0}", distanceB), x + 250, y, 12, vFunBaseMethod.setColorEnum.green); weldCheckTopResult = true; } else { halcon.writeMsg(winHandle, "NG", x - 230, y, 24, vFunBaseMethod.setColorEnum.red); if (!r3) halcon.writeMsg(winHandle, string.Format("焊点数量: {0}", ptnum), x, y, 12, vFunBaseMethod.setColorEnum.red); else halcon.writeMsg(winHandle, string.Format("焊点数量: {0}", ptnum), x, y, 12, vFunBaseMethod.setColorEnum.green); if (!r1) halcon.writeMsg(winHandle, string.Format("焊点位置A: {0}", distanceA), x+130, y, 12, vFunBaseMethod.setColorEnum.red); else halcon.writeMsg(winHandle, string.Format("焊点位置A: {0}", distanceA), x+130, y, 12, vFunBaseMethod.setColorEnum.green); if (!r2) halcon.writeMsg(winHandle, string.Format("焊点位置B: {0}", distanceB), x + 250, y, 12, vFunBaseMethod.setColorEnum.red); else halcon.writeMsg(winHandle, string.Format("焊点位置B: {0}", distanceB), x + 250, y, 12, vFunBaseMethod.setColorEnum.green); weldCheckTopResult = false; } return true; } } catch (Exception ex) { halcon.writeMsg(winHandle, "NG", x - 230, y, 24, vFunBaseMethod.setColorEnum.red); halcon.writeMsg(winHandle, string.Format("焊点数量: {0}", 0), x, y, 12, vFunBaseMethod.setColorEnum.red); halcon.writeMsg(winHandle, string.Format("焊点位置A: {0}", 0), x + 130, y, 12, vFunBaseMethod.setColorEnum.red); halcon.writeMsg(winHandle, string.Format("焊点位置B: {0}", 0), x + 250, y, 12, vFunBaseMethod.setColorEnum.red); halcon.writeMsg(winHandle, string.Format("错误: {0}", ex.Message), x + 370, y, 9, vFunBaseMethod.setColorEnum.red); weldCheckTopResult = false; throw ex; } }
跨线程调用一般VS会在运行期弹出错误提示。有些情况下没有,而且如果你单步拍照、处理图片好像是没什么问题。
但是当你循环处理,并且不sleep的情况下全速来跑,就会发现问题,界面会卡死。
另一个问题是CPU时间过高。
如果在运动控制的程序中,如果CPU占用过高会引发运动异常,搞不好每百次或千次给你来个撞机之类的Bug。或者也可能让机器的运动越来越慢,由原来正常每分钟走6个来回,变成每分钟走2个来回这么奇魄的问题。
但是在halcon视觉处理中,连续处理sleep短暂的话,占用时间高很常见,也没什么好办法处理。
通常,视觉处理时,当前工件和一下个工件有秒级的时间间隙,因此这个问题显得不是那么严重。
我们不可能做到像记事本程序那样,运行几个小时,才占用CPU时间几秒钟。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

