Halcon联合C#编程之内存管理

10.5.2 Calling HALCON Operators

static void HOperatorSet.GrabImage(out HObject image, HTuple acqHandle)
void HImage.GrabImage(HFramegrabber acqHandle)
HImage HFramegrabber.GrabImage()
image(output_object)....................image~HImage(byte/uint2)
acqHandle(intput_control)...............framegrabber~HFramegrabber/HTuple(IntPtr)

如上所示,我们可以使用三个类调用GrabImage函数。当通过Halcon直接导出C#代码时,主要使用HOperatorSet类调用。如果不使用直接导出代码的方式,而是直接在C#环境下编写Halcon代码,官方建议使用其它类去调用函数。

10.5.3 From Declaration to Finalization

 
以下方式只是声明了一个HImage类的变量,该变量尚未引用任何对象
HImage image1;

在这种状态下,不能使用变量调用任何函数;根据编程语言的不同,甚至可能无法将其用作输出参数(例如,在VisualBasic2005中)。但是,可以将HImage对象分配给该变量,例如,函数的返回值:

image1 = Framegrabber.GrabImage();

我们可以在声明该变量的时候进行初始化,如下所示:

HImage Image2 = Framegrabber.GrabImage();
HImage Image3 = null;

我们可以使用IsInitialized函数来判断该变量是否初始化

10.5.3.1 Constructors

与上述不同,下面的声明方式调用了HImage类的空构造函数,创建了一个未初始化的类实例:

HImage Image4 = new HImage();

此类实例可用于调用“类似构造函数”的运算符,如GrabImage,它使用抓取的图像初始化Image4:

Image4.GrabImage(Framegrabber);

除了空的构造函数之外,大多数HALCON/.NET类都提供一个或多个基于HALCON运算符初始化所创建对象的构造函数。例如,HImage提供了一个基于操作符ReadImage的构造函数:

HImage Image5 = new HImage("fuse");//“fuse”可以替换为图片路径名

10.5.3.2 Finalizers

.NET内存管理背后的主要思想是程序员不必担心它,让垃圾回收器删除所有不再使用的对象。HALCON/.NET完全遵循这一理念,为所有类提供相应的终结器,这样即使是非托管资源(例如,与图像采集设备的连接)也可以正确自动地删除。
对于大多数类,终结器会自动调用合适的运算符(如CloseFramegrabber)来释放资源。哪个运算符被调用都列在类的参考手册页中(例如,参见HFramegrabber的条目)。该运算符不能通过类调用,可以在相应的参考手册条目中看到:
static void HOperatorSet.CloseFramegrabber (HTuple acqHandle)
void HFramegrabber.CloseFramegrabber ()

如果您想用不同的参数重新打开连接,甚至不需要调用这样的运算符,因为这是自动完成的。

当使用HFramegrabber等常规类时,请不要通过HOperatorSet调用Close或Clear运算符。

10.5.3.3 Garbage Collection

如上所述,.NET的理念是让垃圾回收器移除未使用的对象。但是,由于垃圾回收器只会不时地删除未使用的对象,因此使用的内存会随之增加(垃圾回收器回收对象是有一定时间间隔的,当其没有开始回收未使用的对象时,内存持续增长。当其开始回收时,内存开始下降。因此内存在一定时间内会表现为先增长后下降的往复运动)。 更重要的是,对于垃圾收集器来说,HALCON的图标变量(Image、Region等)似乎相当“小”,因为它们只包含对数据库中的(在许多情况下相当大)图标对象的引用。因此,即使不再使用这些变量,垃圾回收器也可能无法释放这些变量。 因此,您可能需要强制删除(未使用的)对象。有两种方法:
  • 手动调用垃圾回收器,在计时器事件中调用如下代码:
private void Timer_Tick(object sender, System.EventArgs e)
{
Action();
GC.Collect();
GC.WaitForPendingFinalizers();
}

在托管C++应用程序中调用垃圾回收器的代码是:

GC::Collect();
GC::WaitForPendingFinalizers();
  • 通过调用Dispose方法手动处理单个对象:
HImage Image = new HImage("fuse");
...
Image.Dispose();

除了减少内存消耗外,手动处理对象的另一个原因是释放资源,例如,关闭与图像采集设备或串行接口的连接。

如果要以确定的方式释放引用的资源,则还需要释放包含句柄的HTuple实例。

请注意,HALCON操作符总是为输出参数和返回值创建一个新的对象实例(与10.5.3.1 中的Image4.GrabImage(Framegrabber)不同)。如果变量已经初始化,则其旧内容(以及为其分配的内存)仍然存在,直到垃圾回收器将其删除。如果要手动删除它,则必须在为其分配对象之前调用Dispose。

根据上述内容,VS2017与Halcon18.11联合编程如下:

        private void button1_Click(object sender, EventArgs e)
        {
            HImage image1;                         //未赋值的局部变量,未引用任何对象实例。不能调用任何halcon函数,否则编译失败
            HImage image2 = null;                  //赋值的局部变量,未引用任何对象实例。可以调用halcon函数,且编译成功。但运行会失败,因为未引用任何对象实例
            HImage image3 = new HImage();          //引用了对象实例,但未初始化,Key = 0x0000000000000000
            HImage image4 = new HImage("1.bmp");   //引用了对象实例,并初始化,Key = 0x0000023cb701c6b0

            if (image1.IsInitialized())//编译失败
            {
                int i = 0;
            }
            if (image2.IsInitialized())//运行失败
            {
                int i = 0;
            }
            if (image3.IsInitialized())//未初始化,函数返回false
            {
                int i = 0;
            }
            if (image4.IsInitialized())//初始化,函数返回true
            {
                int i = 0;
            }
        } 
HObject类型的变量可以使用GenEmptyObj函数初始化
HRegion类型的变量可以使用GenEmptyRegion函数初始化

综上所述:

1、当不再使用HObject(HImage、HRegion等图标变量)类型的变量时,一定要手动调用Dispose函数将其释放,否则将造成内存泄露;

2、如果一个HObject类型的变量已经被初始化,那么必须在给它分配新的对象之前手动调用Dispose函数将其旧对象释放,否则将造成内存泄露;

3、image1 = image2,相当于浅拷贝。image1 = image2.CopyObj(1,-1)相当于深拷贝;

4、Halcon17.12版本中HTuple类型不包括Dispose函数,Halcon18.11版本中加入了Dispose函数;

补充内容:

文档名称:quick_guide.pdf
 
章节:2.1.3 HALCON and Parallel Programming
 
Note that HALCON is designed for shared-memory systems , i.e., systems in which multiple processors share a
common memory as it is the case for typical multi-processor or multi-core boards. The main reason is that only in
a shared-memory system threads can share the HALCON object database and do not need to copy images. This
limitation means that HALCON’s parallelization techniques are not suited to the use on workstation clusters or
other multi-processor or multi-core hardware that does not offer shared memory.
 
总结:Halcon是为共享内存多核系统设计的,分布式内存系统与单核系统则无法发挥它的加速效果
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值