Создание экземпляра 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 с родителями).