exponenta event banner

Открытие и закрытие соединения с устройством

Адаптеры обычно открывают соединение с устройством в своих openDevice() и закрыть соединение в их closeDevice() функция. Для большинства устройств, открытие подключения к устройству резервирует его для эксклюзивного использования. При закрытии устройства устройство освобождается.

Примечание

Механизм панели инструментов фактически вызывает IAdaptor класс open() для открытия соединения с устройством и close() функция для закрытия соединения с устройством. Эти функции затем вызывают адаптер openDevice() и closeDevice() функции. Если адаптеру необходимо открыть или закрыть устройство, используйте open() и close() функции, а не вызов openDevice() или closeDevice() непосредственно.

Предлагаемый алгоритм для openDevice ()

openDevice() обычно выполняет следующие задачи.

  1. Проверьте, открыто ли устройство, путем вызова IAdaptor класс isOpen() функция. Если устройство уже открыто, openDevice() функция должна вернуться true. Если устройство еще не открыто, openDevice() должна устанавливать соединение с устройством с помощью вызовов SDK устройства.

  2. Запустите поток сбора данных. Дополнительные сведения см. в разделе Запуск потока сбора данных.

    Примечание

    Запуск отдельного потока требуется только в том случае, если адаптер использует конструкцию на основе потока. Адаптеры также могут использовать асинхронные прерывания (обратные вызовы) для получения кадров, если устройство поддерживает это. В этом сценарии адаптеры получают уведомления асинхронно, когда данные доступны. Сведения об использовании этого метода см. в документации по SDK устройства.

Запуск потока сбора данных

Для запуска потока сбора данных используйте Windows ®CreateThread() функция. CreateThread() создает поток, который выполняется в пределах виртуального адресного пространства вызывающего процесса.

CreateThread() функция принимает эти параметры.

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

Для адаптера в следующей таблице перечислены параметры, которые необходимо задать. Полные сведения о создании потока см. в документе Microsoft Docs.

Параметр

Описание

lpStartAddress

Адрес процедуры потока сбора данных. Укажите имя процедуры потока, объявленной в файле заголовка класса адаптера. См. раздел Реализация функции потока сбора данных.

lpParameter

Указатель на сам объект, т.е. this указатель.

lpThreadId

Адрес переменной, в которой CreateThread() функция возвращает идентификатор, назначенный вновь созданному потоку

После того, как вы позвоните CreateThread() функция, приложения обычно вызывают PostThreadMessage() для отправки сообщения в новый поток. Это приводит к созданию системой очереди сообщений для потока. Введите цикл ожидания, пока поток не подтвердит получение сообщения, чтобы убедиться, что очередь потоков создана. Адаптер завершает поток в адаптере closeDevice() функция - см. Предлагаемый алгоритм для closeDevice ().

Пример: Открытие соединения

В этом примере показана скелетная реализация openDevice() функция.

  1. Замените заглушку реализации openDevice() функции в MyDevice адаптер с этим кодом.

    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. Чтобы иметь возможность компилировать и связывать адаптер, необходимо создать заглушку реализации acquireThread() и добавьте его к адаптеру. Полную реализацию можно заполнить позже - см. Внедрение функции потока сбора данных.

    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. Добавить объявления acquireThread() функция, acquireThread переменная и acquireThreadID переменная в качестве частных элементов данных файла заголовка класса адаптера. В этом примере: 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. Скомпилировать и связать адаптер. Необходимо иметь возможность создания объекта ввода видео. При вызове start убедитесь, что адаптер успешно создал поток сбора данных.

Предлагаемый алгоритм для closeDevice ()

closeDevice() обычно выполняет следующие задачи.

  1. Проверьте, закрыто ли устройство. Если это так, выйдите.

  2. Отправьте сообщение потоку сбора данных для выхода и дождитесь его возвращения перед выходом для адаптеров с конструкциями на основе потоков. Дополнительные сведения об отправке сообщения в поток см. в разделе Отправка сообщения в поток сбора данных.

  3. Закройте дескриптор, связанный с потоком сбора данных, и сбросьте переменную дескриптора потока в значение NULL.

Пример: Закрытие соединения с устройством

В примере показана скелетная реализация closeDevice() функция.

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;
}