Używam biblioteki QtSerialPort do komunikowania się z wirtualnym portem COM przez USB. Port COM zwraca dane i działa prawidłowo podczas testowania z przykładowymi projektami podanymi w QtSerialPort, ale nie działa, gdy uruchamiam go jako część mojego projektu.Utworzenie QtSerialPort w niewłaściwym wątku, powodujące zawieszenie się sygnałów/gniazd
Sprawdziłem łańcuch instancji i wątki prowadzące do instancji QtSerialPort i odkryłem coś dziwnego. Wyniki są poniżej.
main()
MainWindow (Thread 0xbf8dbe0) // Thread "A"
HardwareManager (Thread 0xbf8dbe0) // Thread "A"
QSerialPort (Thread 0xbfb95f0) // Thread "B" !?
W moim kodzie main() funkcja instancję MainWindow, co z kolei instancję HardwareManager i zapisuje go jako zmienną prywatnego. Kiedy instancja HardwareManager jest instancjonowana, tworzy także instancję QSerialPort, dzięki czemu może poprawnie rozmawiać z portem COM.
Jednak zauważysz, że nad moim QSerialPort znajduje się inny wątek niż obiekt nadrzędny, a także jego obiekt nadrzędny (jest w wątku B, podczas gdy obaj przodkowie są w wątku A). Myślę, że ten inny wątek powoduje awarię moich Sygnałów/Slotów. Jeśli I dumpObjectInfo, wyświetla on mój Sygnał/Gniazdo jako skonfigurowany, ale zdarzenia nigdy się nie uruchamiają.
this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData());
Powyżej znajduje się kod, którego używam do utworzenia nowego portu szeregowego i podłączenia go do właściwego gniazda. Rzeczywista konfiguracja bitów, parzystości i danych/bitów stopu odbywa się osobno (i działa poprawnie, jak testowano w przykładowej aplikacji dostarczonej przez QtSerialPort).
Czy ktoś ma wgląd w to, dlaczego ten konkretny obiekt (instancja QSerialPort) jest tworzony w innym wątku? Próbowałem "moveToThread", aby zmienić powiązanie wątku, ale nic nie działa.
Zrobiłem też post on the Qt Project Forums, ale nie miałem jeszcze żadnych użytecznych odpowiedzi.
Edit: Poniżej znajduje się odpowiedni kod w łańcuchu połączenia:
// 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()));
Kiedy QSerialPort jest gotowy do odczytu z (ma danych do dostarczenia), pożary sygnał readyRead
(przynajmniej tak powinno być). Ten sygnał jest uruchamiany poprawnie w projektach Qt przykład, ale nigdy nie dostaję sygnału w mojej aplikacji. Uważam, że powodem, dla którego nie otrzymuję sygnału, są problemy z wątkami.
Nie wiem, jak działa QT, więc tylko dzikie domysły: czy tworzysz 'QSerialPort' w odpowiedzi na jakieś wydarzenie? Czy istnieje jakakolwiek szansa, którą program obsługi zdarzenia wywołał w kontekście innego wątku? –
Nie. Instancja QSerialPort znajduje się w instancji HardwareManager, która znajduje się w instancji MainWindow, która jest wywoływana w metodzie main(). W tym momencie nie ma sygnałów/gniazd/wywołań zwrotnych. –
Uważam, że nie powinieneś zawracać sobie głowy innym wątkiem, powinieneś zawracać sobie głowę niepracującymi sygnałami/gniazdami. Pokaż nam swoją główną, proszę. I podaj trochę informacji o tym, kiedy automat powinien wystrzelić – ixSci