TheImagingSource / ic4-examples

IC4 Example Programs
Apache License 2.0
5 stars 3 forks source link

Device disconnection and reconnection throws #14

Closed 5CoJL closed 4 months ago

5CoJL commented 4 months ago

Hi Tim, image

I'm having an issue where I wish to disconnect from a camera, close the live view (which uses the FloatingDisplay class), reconnect to a device and in theory re open a FloatingDisplay.

However, attempting to open the device throws the exception as seen in the screenshot above, claiming the device is already opened albeit the IsDeviceOpen bool suggests otherwise.

Code for camera disconnection (called with bool close = true in my case): image

Am I getting something wrong for device handling ?

Edit: answered my own question by calling FloatingDisplay.dispose() which should have been an easy thought process :)

Best, Julien

TIS-Tim commented 4 months ago

Hi Julien,

Regarding the device-already-opened problem: I tried to create a little program to reproduce, but it doesn't:

       static void Main(string[] args)
       {
           ic4.Library.Init();

           var cameraName = "DMK 33GX287";

           var display = new ic4.FloatingDisplay();
           var g = new ic4.Grabber();

           g.DeviceOpen(cameraName);
           g.StreamSetup(display);

           Console.WriteLine("Waiting for camera to disappear");
           while ( ic4.DeviceEnum.Devices.SingleOrDefault(d => d.ModelName == cameraName) != null )
           {
               System.Threading.Thread.Sleep(1000);
           }

           g.DeviceClose();

           Console.WriteLine("Waiting for camera to reappear");
           while (ic4.DeviceEnum.Devices.SingleOrDefault(d => d.ModelName == cameraName) == null)
           {
               System.Threading.Thread.Sleep(1000);
           }

           g.DeviceOpen(cameraName);
           g.StreamSetup(display);

           Console.ReadKey();
       }

Does this program work for you as well? If it does not, which version of ic4 and GenTL producer are you using?

5CoJL commented 4 months ago

In my case, the problem arises when I don't wait for the camera to disappear but instead ask for a device close.

Nevertheless, changing the code to

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

ic4.Library.Init();

var cameraName = "DMK 33GX174";

var display = new ic4.FloatingDisplay();
var g = new ic4.Grabber();

g.DeviceOpen(cameraName);
g.StreamSetup(display);

Console.WriteLine("Waiting for camera to disappear");

Console.WriteLine("Close device in 3 seconds...");
await Task.Delay(3000);

g.DeviceClose();
display.Dispose();

Console.WriteLine("Open device in 3 seconds...");
await Task.Delay(3000);

g.DeviceOpen(cameraName);
display = new ic4.FloatingDisplay();
g.StreamSetup(display);

Console.WriteLine("Waiting for camera to reappear");

Console.ReadKey();

does indeed work...

I'll dive deeper into my async mess for some insight. Would you however know why the Grabber.IsDeviceOpen claims "false" yet the exception thrown indicates the device is actually open ? I'm guessing the device could be open through another instance of a grabber I might have not disposed properly, but I'm still a little confused as I only have one Grabber private variable in my code.

TIS-Tim commented 4 months ago

ImageBuffer objects will internally keep the device opened as well, if they point into driver memory. IsDeviceOpened feels a little misleading in a way, since it reports the status of the Grabber object, which is technically correct.

Adding a SnapSink to the test program, snapping a single image and keeping that reference around raises the exception that you see. After all image buffers are disposed, the device can be opened again.

5CoJL commented 4 months ago

Yep, disposing of ImageBuffers does the trick.

Now that you mentionned it, I do remember reading somewhere in the ic4 docs that disposing of ImageBuffers was a best practice... Overlooking is (my) bad !

Thanks a lot for the help.