Main Content

Opening and Closing Connection with a Device

Adaptors typically open a connection with the device in their openDevice() function and close the connection in their closeDevice() function. For most devices, opening a connection to the device reserves it for exclusive use. Closing the device releases the device.

Note

The toolbox engine actually calls the IAdaptor class open() member function to open a connection with a device and the close() function to close a connection with a device. These function then call your adaptor's openDevice() and closeDevice() functions. If your adaptor needs to open or close a device, use the open() and close() functions, rather than calling openDevice() or closeDevice() directly.

Suggested Algorithm for openDevice()

The openDevice() function typically performs the following tasks.

  1. Test whether the device is already open by calling the IAdaptor class isOpen() function. If the device is already open, your openDevice() function should return true. If the device is not already open, your openDevice() function should establish a connection to the device using device SDK calls.

  2. Start the acquisition thread. See Starting an Acquisition Thread for more information.

    Note

    Starting a separate thread is only required if your adaptor uses a thread-based design. Adaptors can also use asynchronous interrupts (callbacks) to acquire frames, if the device supports this. In this scenario, adaptors receive notification asynchronously when data is available. For information about using this method, refer to the documentation for your device's SDK.

Starting an Acquisition Thread

To start an acquisition thread, use the Windows® CreateThread() function. The CreateThread() function creates a thread that executes within the virtual address space of the calling process.

The CreateThread() function accepts these parameters.

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID lpParameter,
  DWORD dwCreationFlags,
  LPDWORD lpThreadId
);

For an adaptor, the following table lists the parameters you must set. For complete information about creating a thread, see Microsoft documentation.

Parameter

Description

lpStartAddress

Address of the acquisition thread procedure. Specify the name of the thread procedure declared in your adaptor class header file. See Implementing the Acquisition Thread Function.

lpParameter

Pointer to the object itself, i.e., the this pointer.

lpThreadId

Address of a variable in which the CreateThread() function returns the ID assigned to the newly created thread

After you call the CreateThread() function, applications typically call the PostThreadMessage() function to send a message to the new thread. This causes the system to create a message queue for the thread. Enter a loop to wait until the thread acknowledges the message was received to ensure that the thread queue has been created. Your adaptor terminates the thread in your adaptor's closeDevice() function — see Suggested Algorithm for closeDevice().

Example: Opening a Connection

This example shows a skeletal implementation of an openDevice() function.

  1. Replace the stub implementation of the openDevice() function in the MyDevice adaptor with this code.

    bool MyDeviceAdaptor::openDevice()
    {
        // If device is already open, return true.
        if (isOpen()) 
            return true;
    
        // Create the image acquistion thread.
        _acquireThread = CreateThread(NULL,
                                         0,
                             acquireThread,
                                      this,
                                         0,
                         &_acquireThreadID);
        if (_acquireThread == NULL) {
            closeDevice();
            return false;
        }
    
        // Wait for thread to create message queue. 
        while(PostThreadMessage(_acquireThreadID,WM_USER+1,0,0) == 0)
            Sleep(1);
    
        return true;
    }
    
  2. To be able to compile and link your adaptor, you must create a stub implementation of your acquireThread() function and add it to your adaptor. You can fill in the complete implementation later — see Implementing the Acquisition Thread Function.

    DWORD WINAPI MyDeviceAdaptor::acquireThread(void* param) {
    
       MSG msg;  
       while (GetMessage(&msg,NULL,0,0) > 0) {
          switch (msg.message) {
             case WM_USER:
    
                // The frame acquisition loop code goes here.
                imaqkit::adaptorWarn(''in acquire thread function \n'');
    
          } // end switch
       } // end while
    
       return 0;
    } // end acquireThread
    
  3. Add declarations of the acquireThread() function, the acquireThread variable, and the acquireThreadID variable as private data members of your adaptor class header file. In this example, MyDeviceAdaptor.h.

    private:
    // Declaration of acquisition thread function
    static DWORD WINAPI acquireThread(void* param);
    
    // Thread variable
    HANDLE _acquireThread;
    
    // Thread ID returned by Windows.
    DWORD _acquireThreadID;
    
  4. Compile and link your adaptor. You should be able to create a video input object. When you call the start function, verify that your adaptor successfully created the acquisition thread.

Suggested Algorithm for closeDevice()

The closeDevice() function typically performs the following tasks.

  1. Test whether the device is already closed. If it is, exit.

  2. Post a message to the acquisition thread to quit and wait until it returns before exiting, for adaptors with thread-based designs. For more information about posting a message to the thread, see Sending a Message to the Acquisition Thread.

  3. Close the handle associated with the acquisition thread and reset the thread handle variable to NULL.

Example: Closing the Connection with a Device

The example shows a skeletal implementation of the closeDevice() function.

bool MyDeviceAdaptor::closeDevice(){

	// If the device is not open, return.
    if (!isOpen())
        return true;

    // Terminate and close the acquisition thread.
    if (_acquireThread) {
        // Send WM_QUIT message to thread.
        PostThreadMessage(_acquireThreadID, WM_QUIT, 0, 0);

        // Give the thread a chance to finish.
        WaitForSingleObject(_acquireThread, 10000);

        // Close thread handle.
        CloseHandle(_acquireThread);
        _acquireThread = NULL;
    }
	return true;
}