2013-03-01 2 views
10

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

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

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

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

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

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

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

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

Я также сделал post on the Qt Project Forums, но пока не получил полезных ответов.

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

// 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, но я никогда не получаю сигнал в своем приложении. Я считаю, что причина, по которой я не получаю сигнал, связана с этими проблемами.

+1

Я не знаю, как работает QT, так что просто дикое предположение: вы создаете 'QSerialPort' в ответ на какое-то событие? Любой шанс, вызванный обработчиком событий в контексте другого потока? – 2013-03-01 16:01:36

+0

Нет. Репликация QSerialPort входит в экземпляр HardwareManager, который находится в экземпляре MainWindow, который вызывается в методе main(). На данный момент не используются сигналы/слоты/обратные вызовы. –

+0

Я считаю, что вам не следует беспокоиться о другой теме, вы должны беспокоиться о том, что не работают только сигнальные/слоты. Покажите нам свой главный, пожалуйста. И дайте некоторую информацию о том, когда должен сломать слот. – ixSci

ответ

1

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

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

2

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

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

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

Кроме того, this post, по-видимому, предполагает, что вы не должны устанавливать родителя для QtSerialPort (возможно, потому что moveToThread не работает с QObjects с родителями).

+0

Добавление параметра Qt :: QueuedConnection не требуется, поскольку по умолчанию Qt :: AutoConnection (я использую Qt 5, не уверен о Qt 4) также правильно обрабатывает соединения между различными потоками. – FourtyTwo

Смежные вопросы