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
版权声明:本文为博主原创文章,转载请附上博文链接!