TheImagingSource / IC-Imaging-Control-Samples

Windows Sample in C#, C++, Python, LabVIEW and Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`TIS.Imaging.ICImagingControl()` is not released properly and cause memory leaks

NatanBagrov opened this issue · comments

Hello,

I reference the issue with this line of code:

ic = TIS.Imaging.ICImagingControl()

When wrapping the referenced file with a for loop, the memory explodes. I've isolated the relevant line (above).
Apparently, ic.LiveStop() (line 82) does not release all resources.

Any suggestions? I don't want to keep ic as some global state.

Best regards!

Hello

ic.LiveStop() stops the live video stream only. But it keeps the used video capture device open, so you can call ic.LiveStart() again.
If you want to release as much as possible resources, you must delete the created ic object instance. I must admit, I am not that Python expert, so I do not know, how to delete that. But I guess, you know that.
I hope, in the for loop you have the trhee lines

snapsink.SnapSingle(TimeSpan.FromSeconds(5))
frame = snapsink.SnapSingle(TimeSpan.FromSeconds(5))
TIS.Imaging.FrameExtensions.SaveAsJpeg( frame,"image.jpg", 75)

only. Putting the complete code into a for loop does not make any sense,

Stefan

Hi Stefan,
The for loop is just an example. If I have a TCP server, and this function as callback - the function will be called on every request, and I don't want to have ic as a persistent state.
I cannot just delete ic using "Python" because it is create via an external library, TIS.Imaging.ICImagingControl35.dll - so the library should provide some API to manage it, which I guess it does, but the code sample does not use it.

As far as I know,
ic = TIS.Imaging.ICImagingControl()
is the same as
TIS.Imaging.ICImagingControl() ic = new TIS.Imaging.ICImagingControl() ;
in C#
If I put that into a function like

private void image()
{
    TIS.Imaging.ICImagingControl ic = new TIS.Imaging.ICImagingControl() ;
}
```The "ic" lives are long as I stay in the function. It is deleted or marked for deletion, when the function is left. The C# garbage collector should sooner or later free the memory. This can be forced by

private void image()
{
TIS.Imaging.ICImagingControl ic = new TIS.Imaging.ICImagingControl() ;
ic.dispose();
gc.collect();
}

I am not sure, whether there is a similar thing in Python.  It may also is a good idea, what PythonNet does in this case http://pythonnet.github.io. At the end of the page is some code with "using" That would translate to
with ic = TIS.Imaging.ICImagingControl():
     ' open device, configre device, get images, close device...
I found that at Stackoverflow: https://stackoverflow.com/questions/1369526/what-is-the-python-keyword-with-used-for
It seems to answer your question regarding the resources and is worth a try,

Stefa

In C# it works because C# has its garbage collector, and this object is a managed resource there. Furthermore, the with statement does not work because TIS.Imaging.ICImagingControl (in Python) does not implement __enter__ nor __exit__.

Any chance to check with the development team how to dispose this object via Python, and release the memory allocated by it?

Did you try the

with ic = TIS.Imaging.ICImagingControl():
     ' open device, configre device, get images, close device...

python code? (I just see, that my previous answer above is nicely mal-formatted...)

Stefan

Hello

the "with" thingy does not work. But "ic.Dispose()" does the job:

import ctypes as C
import msvcrt as m
# Import PyhtonNet
import clr
# Load IC Imaging Control .NET 
clr.AddReference('TIS.Imaging.ICImagingControl35')

# Import the IC Imaging Control namespace.
import TIS.Imaging

print("start")
m.getch()
print("started")

for r in range(100):
    ic =  TIS.Imaging.ICImagingControl()
    ic.Device="DFK Z30GP031"
    ic.LiveStart()
    ic.LiveStop()
    ic.Device = ""
    ic.Dispose()

print("done")

m.getch()

I hope, this works for you.

Stefan

Hi Stefan,
Looks like it did the trick. I've added a pull-request as-well.

Hello

Thank you for the pull request. I merged that, but from my point of view, it should not be necessary in the sample, because I would expect the Python garbage collector to clean up memory automatically on program end. However, I can be wrong here, because I am not Python expert.

Stefan

Hello

Thank you for the pull request. I merged that, but from my point of view, it should not be necessary in the sample, because I would expect the Python garbage collector to clean up memory automatically on program end. However, I can be wrong here, because I am not Python expert.

Stefan

You are half correct - this memory will be released, but not by Python's garbage collector, because it is unmanaged resource. It will be released by Windows, once the Python program will terminate.
The problem is that programmers might (and will) copy the sample code to somewhere in the middle of their application - resulting a memory leak.

Hello

Thank you for informing me about this. It is highly appreciated!

Stefan