Создание экземпляра QtSerialPort в неправильном потоке, что приводит к сбою сигналов / слотов

Я использую библиотеку QtSerialPort для общения с виртуальным COM-портом через USB. COM-порт возвращает данные и работает должным образом при тестировании с примерами проектов, предоставленных с QtSerialPort, но завершается неудачно, когда я запускаю его как часть моего проекта.

Я проверил цепочку создания экземпляров и потоки, которые приводят к созданию экземпляра QtSerialPort, и обнаружил кое-что немного странное. Результаты ниже.

main()
  MainWindow (Thread 0xbf8dbe0)        // Thread "A"
    HardwareManager (Thread 0xbf8dbe0) // Thread "A"
      QSerialPort (Thread 0xbfb95f0)   // Thread "B" !?

В моем коде функция main() создает экземпляр MainWindow, который, в свою очередь, создает экземпляр HardwareManager и сохраняет его как частную переменную. Когда создается экземпляр HardwareManager, он также создает экземпляр QSerialPort, чтобы он мог правильно общаться с COM-портом.

Тем не менее, вы заметите, что выше мой QSerialPort находится в другом потоке, чем родительский объект, а также его родительский объект (он находится в потоке B, в то время как оба предка находятся в потоке A). Я думаю, что этот другой поток вызывает сбой моих сигналов / слотов. Если я дам dumpObjectInfo, он перечислит мой сигнал / слот как настроенный, но события никогда не сработают.

this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData());

Выше приведен код, который я использую для создания нового последовательного порта и подключения его к соответствующему слоту. Фактическая конфигурация скорости передачи, четности и данных / стоп-бита происходит отдельно (и работает должным образом, как проверено в примере приложения, предоставляемого QtSerialPort).

Кто-нибудь знает, почему этот конкретный объект (экземпляр QSerialPort) создается в другом потоке? Я пытался "moveToThread", чтобы переключить ассоциацию потоков, но, похоже, ничего не работает.

Я также сделал сообщение на форумах Qt Project, но пока не получил полезных ответов.

Изменить: ниже приведен соответствующий код в цепочке вызовов:

// main()
QApplication a(argc, argv)
MainWindow window = new MainWindow(); // [1]
MainWindow.show();
return a.exec();

// MainWindow::MainWindow() [1]
this->toolController = new QtToolController(this);
HardwareManager *manager = new HardwareManager(this->toolController); // [2]

// HardwareManager::HardwareManager() [2]
this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));

Когда QSerialPort готов для чтения (он имеет данные для предоставления), он запускает readyRead сигнал (по крайней мере, он должен). Этот сигнал срабатывает должным образом в проектах примера Qt, но я никогда не получаю сигнал в своем приложении. Я полагаю, что причина, по которой я не получаю сигнал, из-за проблем с потоками

2 ответа

Решение

В духе обеспечения доступности ответов для всех, кто сталкивался с этой проблемой, проблема была связана со сборками Release/Debug. Библиотека QtSerialPort была собрана ТОЛЬКО для моей среды Release, и по какой-либо причине при запуске моего приложения в режиме отладки ссылка на Release QtSerialPort была бы связана с потерей контекста потока.

Чтобы это исправить, я убедился, что собрал правильную версию библиотеки, а затем сделал ссылку на правильную версию для своей среды.

Вы можете использовать QueuedConnection для перехвата сигналов из другого потока.

connect(this->serial, SIGNAL(readyRead()), 
    this, SLOT(readSerialData()), Qt::QueuedConnection);

Таким образом, слот должен выполняться в контексте вашего основного потока, как только элемент управления возвращается в свой цикл обработки событий.

Кроме того, этот пост, кажется, предлагает вам не устанавливать родителя для QtSerialPort (вероятно, потому что moveToThread не работает на объектах QObjects с родителями).

Другие вопросы по тегам