Skip to content

EnumerationEvents_CSharp

EnumerationEvents_CSharp.cs explores arrival and removal events on interfaces and the system. It relies on information provided in the Enumeration_CSharp, Acquisition_CSharp, and NodeMapInfo_CSharp examples.


//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================

/**
 *  @example EnumerationEvents_CSharp.cs
 *
 *  @brief EnumerationEvents_CSharp.cs explores arrival and removal events on
 *  interfaces and the system. It relies on information provided in the
 *  Enumeration_CSharp, Acquisition_CSharp, and NodeMapInfo_CSharp examples.
 *
 *  It can also be helpful to familiarize yourself with the
 *  NodeMapCallback_CSharp example, as nodemap callbacks follow the same
 *  general procedure as events, but with a few less steps.
 *
 *  This example creates a user-defined class, InterfaceEventListener. It allows
 *  the user to define any properties, parameters, and the event itself while
 *  the parent class, ManagedInterfaceEventHandler, allows the child class to interface
 *  with the Spinnaker SDK.
 *
 *  Please leave us feedback at: https://www.surveymonkey.com/r/TDYMVAPI
 *  More source code examples at: https://github.com/Teledyne-MV/Spinnaker-Examples
 *  Need help? Check out our forum at: https://teledynevisionsolutions.zendesk.com/hc/en-us/community/topics
 */

using System;
using System.Collections.Generic;
using SpinnakerNET;
using SpinnakerNET.GenApi;
using System.Threading;

namespace EnumerationEvents_CSharp
{
    class Program
    {
        // This class defines the properties and methods for device arrivals and removals
        // on an interface. Take special note of the signatures of the OnDeviceArrival()
        // and OnDeviceRemoval() methods. Also, enumeration event listeners must inherit
        // from ManagedInterfaceEventHandler whether they are to be registered to the system
        // or an interface.
        class InterfaceEventListener : ManagedInterfaceEventHandler
        {
            private bool registerToSystem;
            private string interfaceID;
            private IManagedInterface managedInterface;
            private IManagedSystem managedSystem;

            //
            // Set the constructor
            //
            // *** NOTES ***
            // When constructing a generic InterfaceEventListener to be registered to the system,
            // the handler will not have knowledge of which interface triggered the event callbacks.
            // On the other hand, InterfaceEventListener does not need knowledge about the system if we
            // are constructing it to be registered to a specific interface.
            //
            public InterfaceEventListener(string ifaceID, IManagedInterface manIface)
            {
                interfaceID = ifaceID;
                managedInterface = manIface;
                registerToSystem = false;
            }

            public InterfaceEventListener(IManagedSystem manSystem)
            {
                managedSystem = manSystem;
                registerToSystem = true;
                interfaceID = "";
            }

            // This method defines the arrival event callback on an interface. It prints out
            // the device serial number of the camera arriving and the interface ID.
            // The argument is the serial number of the camera that triggered the arrival event.
            // If the event handler was constructed to be registered to the system as a generic
            // InterfaceEventListener, then we just retrieve the number of cameras
            // currently connected on the system and print it out.
            protected override void OnDeviceArrival(IManagedCamera camera)
            {
                if (registerToSystem)
                {
                    int deviceCount = managedSystem.GetCameras().Count;
                    PrintGenericHandlerMessage(deviceCount);
                }
                else
                {
                    Console.WriteLine("Interface event listener:");
                    Console.WriteLine(
                        "\tDevice {0} has arrived on interface {1}.\n", camera.GetDeviceSerialNumber(), interfaceID);
                }
            }

            // This method defines the removal event callback on an interface. It prints out the
            // device serial number of the camera being removed and the interface ID.
            // The argument is the serial number of the camera that triggered the removal event.
            // If the event handler was constructed to be registered to the system as a generic
            // InterfaceEventListener, then we just retrieve the number of cameras
            // currently connected on the system and print it out.
            protected override void OnDeviceRemoval(IManagedCamera camera)
            {
                if (registerToSystem)
                {
                    int deviceCount = managedSystem.GetCameras().Count;
                    PrintGenericHandlerMessage(deviceCount);
                }
                else
                {
                    Console.WriteLine("Interface event listener:");
                    Console.WriteLine(
                        "\tDevice {0} was removed from interface {1}.\n", camera.GetDeviceSerialNumber(), interfaceID);
                }
            }

            // Helper function to print the number of devices on an interface event registered to the system.
            private void PrintGenericHandlerMessage(int deviceCount)
            {
                Console.WriteLine("Generic interface event handler:");
                bool singular = deviceCount == 1;
                Console.WriteLine(
                    "\tThere {0} {1} {2} on the system.\n",
                    (singular ? "is"
                     : "are"),
                    deviceCount,
                    (singular ? "device"
                     : "devices"));
            }

            // This method returns the interface ID that the interface event handler is bound to.
            public string GetInterfaceId()
            {
                return interfaceID;
            }
        }

        // This class defines the properties and methods of the system event listener that handles
        // interface arrival and removal events on the system. Take special note of the signatures
        // of the OnInterfaceArrival() and OnInterfaceRemoval() methods.
        // Interface enumeration event handlers must inherit from ManagedSystemEventHandler.
        class SystemEventListener : ManagedSystemEventHandler
        {
            private ManagedSystem system;
            private readonly Mutex eventListenersMutex;
            private List<InterfaceEventListener>interfaceEventListeners;
            private InterfaceEventListener interfaceEventListenerOnSystem;

            public SystemEventListener(ManagedSystem sys)
            {
                system = sys;
                eventListenersMutex = new Mutex();
                interfaceEventListeners = new List<InterfaceEventListener>();
            }

            // This method defines the interface arrival event callback on the system.
            // It first prints the ID of the arriving interface, then
            // registers the interface event on the newly arrived interface.
            //
            // *** NOTES ***
            // Only arrival events for GEV interfaces are currently supported.
            protected override void OnInterfaceArrival(IManagedInterface iface)
            {
                Console.WriteLine("System event handler:");
                Console.WriteLine("\tInterface '{0}' has arrived on the system.\n", iface.TLInterface.InterfaceID);

                // UpdateInterfaceList() only updates newly arrived or newly removed interfaces.
                // In particular, after this call:
                //
                // - Any pre-existing interfaces will still be valid.
                // - Newly removed interfaces will be invalid.
                //
                // *** NOTES ***
                // - Invalid interfaces will be re-validated if the interface comes back (arrives) with the same
                // interface ID. If the interface ID changes, you can use the pointer populated by this callback or
                // you must get the new interface object from the updated interface list in order to access this
                // interface.
                //
                // - Interface indices used to access an interface with GetInterfaces() may change after updating the
                // interface list. The interface at a particular index cannot be expected to remain at that index after
                // calling UpdateInterfaceList().
                system.UpdateInterfaceList();

                // Select interface
                INodeMap nodeMap = iface.GetTLNodeMap();

                IString interfaceIDNode = nodeMap.GetNode<IString>("InterfaceID");

                ManagedCameraList cameraList = iface.GetCameras();
                int numCameras = cameraList.Count;
                for (uint camIdx = 0; camIdx < numCameras; camIdx++)
                {
                    IManagedCamera manCamera = cameraList.GetByIndex(camIdx);
                    INodeMap nodeMapTLDevice = manCamera.GetTLDeviceNodeMap();
                    IString deviceSerialNode = nodeMapTLDevice.GetNode<IString>("DeviceSerialNumber");
                    if (deviceSerialNode != null && deviceSerialNode.IsReadable)
                    {
                        string deviceSerialNumber = deviceSerialNode.Value;
                        Console.WriteLine(
                            "\tDevice {0} is connected to interface '{1}'.",
                            deviceSerialNumber,
                            iface.TLInterface.InterfaceID);
                    }
                }

                // Create interface event
                {
                    eventListenersMutex.WaitOne();

                    try
                    {
                        InterfaceEventListener interfaceEventListener =
                            new InterfaceEventListener(iface.TLInterface.InterfaceID, iface);
                        interfaceEventListeners.Add(interfaceEventListener);

                        // Register interface event listener
                        iface.RegisterEventHandler(interfaceEventListener);
                        Console.WriteLine(
                            "Event handler registered to interface '{0}'...\n", iface.TLInterface.InterfaceID);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(
                            "Error registering interface event handler to '{0}': {1}",
                            iface.TLInterface.InterfaceID,
                            ex.Message);
                    }
                    finally
                    {
                        eventListenersMutex.ReleaseMutex();
                    }
                }
            }

            // This method defines the interface removal event callback on the system.
            // It prints the ID of the interface removed.
            //
            // *** NOTES ***
            // Only removal events for GEV interfaces are currently supported.
            protected override void OnInterfaceRemoval(IManagedInterface iface)
            {
                Console.WriteLine("System event handler:");
                Console.WriteLine("\tInterface '{0}' was removed from the system.\n", iface.TLInterface.InterfaceID);

                // Interface indices used to access an interface with GetInterfaces() may change after updating the
                // interface list. The interface at a particular index cannot be expected to remain at that index after
                // calling UpdateInterfaceList().
                system.UpdateInterfaceList();

                // Find the event handler that was registered to the removed interface and remove it.
                // Interface event handlers are automatically unregistered when the interface is removed so it is not
                // necessary to manually unregister them.
                {
                    eventListenersMutex.WaitOne();
                    try
                    {
                        int handlerIdx = 0;
                        for (handlerIdx = 0; handlerIdx < interfaceEventListeners.Count; handlerIdx++)
                        {
                            if (interfaceEventListeners[handlerIdx].GetInterfaceId() == iface.TLInterface.InterfaceID)
                            {
                                interfaceEventListeners.RemoveAt(handlerIdx);
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(
                            "Error erasing event hander from interface '{0}': {1}",
                            iface.TLInterface.InterfaceID,
                            ex.Message);
                    }
                    finally
                    {
                        eventListenersMutex.ReleaseMutex();
                    }
                }
            }

            public void RegisterInterfaceEventToSystem()
            {
                if (interfaceEventListenerOnSystem == null)
                {
                    //
                    // Create interface event listener for the system
                    //
                    // *** NOTES ***
                    // The InterfaceEventListener has been constructed to accept a system object in
                    // order to print the number of cameras on the system.
                    //
                    interfaceEventListenerOnSystem = new InterfaceEventListener(system);
                }

                //
                // Register interface event handler for the system
                //
                // *** NOTES ***
                // Arrival, removal, and interface event handlers can all be registered to
                // interfaces or the system. Do not think that interface event handlers can only be
                // registered to an interface. An interface event is merely a combination
                // of an arrival and a removal event.
                // Only arrival and removal events for GEV interfaces are currently supported.
                //
                // *** LATER ***
                // Arrival, removal, and interface event handlers must all be unregistered manually.
                // This must be done prior to releasing the system and while they are still
                // in scope.
                //
                system.RegisterEventHandler(interfaceEventListenerOnSystem);
                Console.WriteLine("Interface event handler registered on the system...");
            }

            public void UnregisterInterfaceEventFromSystem()
            {
                //
                // Unregister interface event handler from system object
                //
                // *** NOTES ***
                // It is important to unregister all arrival, removal, and interface event handlers
                // registered to the system.
                //
                if (interfaceEventListenerOnSystem != null)
                {
                    system.UnregisterEventHandler(interfaceEventListenerOnSystem);
                    Console.WriteLine("Interface event handler unregistered from system...");
                    interfaceEventListenerOnSystem = null;
                }
            }

            public void RegisterAllInterfaceEvents()
            {
                {
                    eventListenersMutex.WaitOne();

                    if (interfaceEventListeners.Count != 0)
                    {
                        interfaceEventListeners.Clear();
                    }

                    eventListenersMutex.ReleaseMutex();
                }

                ManagedInterfaceList interfaceList = system.GetInterfaces();
                int numInterfaces = interfaceList.Count;

                //
                // Create and register interface event handler to each interface
                //
                // *** NOTES ***
                // The process of event handler creation and registration on interfaces is similar
                // to the process of event handler creation and registration on the system. The
                // InterfaceEventListener class has been written to accept an interface and an
                // interface ID to differetiate between the interfaces.
                //
                // *** LATER ***
                // Arrival, removal, and interface event handlers must all be unregistered manually.
                // This must be done prior to releasing the system and while they are still
                // in scope.
                //
                for (uint i = 0; i < numInterfaces; i++)
                {
                    // Select interface
                    IManagedInterface manInterface = interfaceList.GetByIndex(i);
                    INodeMap nodeMap = manInterface.GetTLNodeMap();

                    IString interfaceIDNode = nodeMap.GetNode<IString>("InterfaceID");
                    // Ensure the node is valid
                    if (interfaceIDNode == null || !interfaceIDNode.IsReadable)
                    {
                        continue;
                    }

                    string interfaceID = interfaceIDNode.Value;

                    {
                        eventListenersMutex.WaitOne();
                        try
                        {
                            // Create interface event handler
                            InterfaceEventListener interfaceEventListener =
                                new InterfaceEventListener(interfaceID, manInterface);
                            interfaceEventListeners.Add(interfaceEventListener);

                            // Register interface event handler
                            manInterface.RegisterEventHandler(interfaceEventListener);

                            Console.WriteLine("Event handler registered to interface '{0}'...", interfaceID);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(
                                "Error erasing event hander from interface '{0}': {1}", interfaceID, ex.Message);
                        }
                        finally
                        {
                            eventListenersMutex.ReleaseMutex();
                        }
                    }
                }
                Console.WriteLine();
            }

            public void UnregisterAllInterfaceEvents()
            {
                ManagedInterfaceList interfaceList = system.GetInterfaces(false);
                int numInterfaces = interfaceList.Count;

                eventListenersMutex.WaitOne();
                //
                // Unregister interface event handler from each interface
                //
                // *** NOTES ***
                // It is important to unregister all arrival, removal, and interface event handlers
                // from all interfaces that they may be registered to.
                //
                for (uint i = 0; i < numInterfaces; i++)
                {
                    // Select interface
                    IManagedInterface manInterface = interfaceList.GetByIndex(i);
                    INodeMap nodeMap = manInterface.GetTLNodeMap();

                    IString interfaceIDNode = nodeMap.GetNode<IString>("InterfaceID");
                    // Ensure the node is valid
                    if (interfaceIDNode == null || !interfaceIDNode.IsReadable)
                    {
                        continue;
                    }

                    string interfaceID = interfaceIDNode.Value;
                    {
                        try
                        {
                            foreach(InterfaceEventListener listener in interfaceEventListeners)
                            {
                                if (interfaceID == listener.GetInterfaceId())
                                {
                                    manInterface.UnregisterEventHandler(listener);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(
                                "Error erasing event hander from interface '{0}': {1}", interfaceID, ex.Message);
                        }
                    }
                }

                interfaceEventListeners.Clear();
                Console.WriteLine("Event handler unregistered from interfaces...");
                eventListenersMutex.ReleaseMutex();
            }
        }

        // This function checks if GEV enumeration is enabled on the system.
        static void CheckGevEnabled(ManagedSystem pSystem)
        {
            // Retrieve the System TL Nodemap and EnumerateGEVInterfaces node.
            INodeMap nodeMapTLSystem = pSystem.GetTLNodeMap();
            IBool enumerateGevInterfacesNode = nodeMapTLSystem.GetNode<IBool>("EnumerateGEVInterfaces");

            // Ensure the node is valid.
            if (enumerateGevInterfacesNode != null && enumerateGevInterfacesNode.IsReadable)
            {
                bool gevEnabled = enumerateGevInterfacesNode.Value;

                // Check if node is enabled.
                if (!gevEnabled)
                {
                    Console.WriteLine("\nWARNING: GEV Enumeration is disabled.");
                    Console.WriteLine("If you intend to use GigE cameras please run the EnableGEVInterfaces shortcut");
                    Console.WriteLine("or set EnumerateGEVInterfaces to true and relaunch your application.\n");
                    return;
                }
            }
            else
            {
                Console.WriteLine("EnumerateGEVInterfaces node is unavailable");
                return;
            }

            Console.WriteLine("EnumerateGEVInterfaces is enabled. Continuing..");
        }

        // Example entry point; this function sets up the example to act
        // appropriately upon arrival and removal events; please see
        // Enumeration_CSharp example for more in-depth comments on
        // preparing and cleaning up the system.
        static int Main(string[] args)
        {
            Program program = new Program();

            // Retrieve singleton reference to system object
            ManagedSystem system = new ManagedSystem();

            // Print out current library version
            LibraryVersion spinVersion = system.GetLibraryVersion();
            Console.WriteLine(
                "Spinnaker library version: {0}.{1}.{2}.{3}\n\n",
                spinVersion.major,
                spinVersion.minor,
                spinVersion.type,
                spinVersion.build);

            // Check if GEV enumeration is enabled
            CheckGevEnabled(system);

            // Retrieve list of cameras from the system
            ManagedCameraList camList = system.GetCameras();

            Console.WriteLine("Number of cameras detected: {0}\n", camList.Count);

            // Retrieve list of interfaces from the system
            ManagedInterfaceList interfaceList = system.GetInterfaces();

            Console.WriteLine("Number of interfaces detected: {0}\n", interfaceList.Count);

            Console.WriteLine("\n*** CONFIGURING ENUMERATION EVENTS ***\n");

            //
            // Create system event listener
            //
            // *** NOTES ***
            // The SystemEventListener has been written to accept a system object in
            // the constructor in order to register/unregister events to/from the system object
            //
            SystemEventListener systemEventListener = new SystemEventListener(system);

            //
            // Register system event to the system
            //
            // *** NOTES ***
            // A system event is merely a combination of an interface arrival and an
            // interface removal event.
            // This feature is currently only supported for GEV interface arrivals and removals.
            //
            // *** LATER ***
            // Interface arrival and removal events must all be unregistered manually.
            // This must be done prior to releasing the system and while they are still
            // in scope.
            //
            system.RegisterEventHandler(systemEventListener);

            systemEventListener.RegisterInterfaceEventToSystem();
            systemEventListener.RegisterAllInterfaceEvents();

            // Wait for user to plug in and/or remove camera devices
            Console.WriteLine("\nReady! Remove/Plug in cameras to test or press Enter to exit...\n");
            Console.ReadLine();

            systemEventListener.UnregisterAllInterfaceEvents();
            systemEventListener.UnregisterInterfaceEventFromSystem();

            //
            // Unregister system event handler from system object
            //
            // *** NOTES ***
            // It is important to unregister all interface arrival and removal event handlers
            // registered to the system.
            //
            system.UnregisterEventHandler(systemEventListener);

            Console.WriteLine("System event handler unregistered from system...");

            // Clear camera list before releasing system
            camList.Clear();

            // Clear interface list before releasing system
            interfaceList.Clear();

            // Release system
            system.Dispose();

            Console.WriteLine("\nDone! Press Enter to exit...");
            Console.ReadLine();

            return 0;
        }
    }
}