Comunicazione fra threads
-
Salve ragazzi.
Provo a descrivere la situazione che mi si presenta e il problema ad esso connesso.Nella mia applicaizone ho due Threads:
- Un TCPThread (un thread di ascolto su di un Socket) che viene creato nella main page (figlio quindi del thread GUI)
- Il main Thread (GUI) che fa funzionare tutta l'applicazione...
L'utente quindi utilizza l'applicazione gestita dal main thread e può interagire con una serie di dialog. Diaciamo che l'utente a questo punto crea il Dialog1 che crea il Dialog2 etc... In questa situazione ho necessità che il Dialog3 riceva dei dati che il thread TCP sta registrando.
Nella mia infinita ignoranza avrei ustato una CONNECT se il thread TCP e il Dialog3 fossero stati tutti figli del solito dialog, ma così non è... Uno infatti è figlio di Dialog2 e uno di Mainpage(o GUIthread che dir si voglia).
Avete qualche consiglio da darmi? Ve ne sarei infinitamente grato.
-
Probabilmente devi semplicemente creare una catena di signals o passare un puntatore all'oggetto che emette i segnali dal TCP. Io preferisco la prima soluzione quindi:
- creerei un signal in Dialog1 che e' identico a quello emesso dal TCP object, da Mainpage connetti il signal nell'oggetto TCP con quello in Dialog1.
- creerei un signal in Dialog2 che e' identico a quello in Dialog1 e in Dialog1 connetti i due segnali
- In Dialog2 connetti il segnale in Dialog2 con lo slot in Dialog3
-
@VRonin
Capito Ronin. Grazie per la risposta ;) -
Allora dopo un po' di tempo sono tornato ad occuparmi del problema dei thread...
L'ultima volta avevo capito che il tuo consiglio consisteva in questo:Lancio il mio thread in mainwindow
TCPThread *thread = new TCPThread; thread->start();
faccio le mie cose e poi collego mainwindow con dialog1
Dialog1 *dia1=new Dialog1(); dia1->setModal(true); connect(this, SIGNAL(sendIdThread(const TCPThread &) ), dia1, SLOT( getIdThread(const TCPThread & ))); emit sendIdThread(*thread); dia1->exec();
stessa cosa farò in Dialog2 e Dialog3
Dialog2 *dia2=new Dialog2(); dia2->setModal(true); connect(this, SIGNAL(sendIdThread(const TCPThread &) ), dia2, SLOT( getIdThread(const TCPThread & ))); emit sendIdThread(*thread); dia2->exec();
etc..
Così finalmente odvrei avere il riferimento al thread nel mio dialog 3. Ho capito bene?
Il problema che incontro è che già durante il primo passaggio di riferimento nello slot getIdThread(const TCPThread & ) prendo questo errore:
`error: use of deleted function 'TCPThread::TCPThread(const TCPThread&)' case 7: _t->getIdThread((*reinterpret_cast< const TCPThread(*)>(_a[1]))); break;
Sapresti indicarmi cosa sbaglio? Grazie mille per la disponibilità
-
TCPThread
e' unQObject
e iQObject
non possono essere copiati. usa i puntatori invece delle referenze:const TCPThread&
deve diventareTCPThread*
(probabilmente il const e' un po' troppo restrittivo, io l'ho tolto ma lo puoi tenere se pensi sia accettabile)P.S.
Di solitoQThread
non va reimplementato, protesti postare il codice diTCPThread
? -
@VRonin
intanto grazie per la risposta. Il codice del thread è :.H #ifndef TCPTHREAD_H #define TCPTHREAD_H #include "utility/speaktts.h" #include <QDialog> #include <QMainWindow> #include <QTcpSocket> #include <QThread> namespace Ui { class TCPThread; } class TCPThread : public QThread { Q_OBJECT public slots: void connectToHost(); void connected(); void readServer(); void sendMessage(); void delay( int millisecondsToWait ); private slots: void on_sendMessage_clicked(); void on_control_clicked(); private: Ui::TCPThread *ui; void run(); QTcpSocket *socket; SpeakTTS *tts; }; #endif // TCPTHREAD_H
.C #include "tcpthread.h" #include "utility/speaktts.h" #include <QtGui> #include <QtNetwork> #include <QFormLayout> #include <QLineEdit> #include <QSpinBox> #include <QPushButton> #include <QTextEdit> #include <QString> #include <QTime> #include <QThread> #include <QtMath> #include <QVector> typedef struct { long quotaX; //coord x long quotaY; //coord y long flags; //touch long progressivo; }DATI; void TCPThread::run() { //Creo il socket TCP socket=new QTcpSocket(); connect(socket, SIGNAL(connected()), this, SLOT(connected())); connect(socket, SIGNAL(readyRead()), this, SLOT(readServer())); this->connectToHost(); bool connected=false; //Cicolo infinito di ascolto while(1){ //Se la connessione esiste invio il messaggio connected = (socket->state() == QTcpSocket::ConnectedState); if(connected){ //Invio un messaggio di "polling" per ricevere le coordinate dal server sendMessage(); delay(250); //La connessione non esiste/è caduta, la ripristino }else{ // qDebug() << "Stauts: abort "; socket->abort(); socket->connectToHost(QHostAddress("192.168.2.115"), 5000); delay(2000); // qDebug() << "Stauts: connect "; } } } //Stabilisce la connessione con il server void TCPThread::connectToHost(){ socket->connectToHost(QHostAddress("192.168.2.115"), 5000); } void TCPThread::connected(){ socket->write(QString("Hello Server").toLatin1()); socket->waitForBytesWritten(); } void TCPThread::sendMessage(){ //Invio un qualsiasi messaggio per avere la risposta coi dati socket->write(QString("a").toLatin1()); //ui->trace->append("Ho inviato il messaggio"); socket->waitForBytesWritten(); } void TCPThread::readServer(){ if(socket->bytesAvailable() < sizeof(DATI)) return; const QByteArray raw = socket->read(sizeof(DATI)); const DATI* const rawData = reinterpret_cast<const DATI*>(raw.constData()); qDebug() << "Coord X: " + QString::number(rawData->quotaX) << "Coord Y: " + QString::number(rawData->quotaY) << "Touch: " + QString::number(rawData->flags); if(rawData->flags==0){ qDebug() << "Coord X: " + QString::number(rawData->quotaX) << "Coord Y: " + QString::number(rawData->quotaY) << "Touch: " + QString::number(rawData->flags); } readServer(); } //Evento click pulsante messaggio void TCPThread::on_sendMessage_clicked() { this->sendMessage(); } //Evento click pulsante connetti void TCPThread::on_control_clicked() { this->connectToHost(); } //Funzione per impostare il delay in millisecondi void TCPThread::delay( int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } }
Che fondamentalmente manda un messaggio di un carattere ad un server che gli risponde sempre con 3 valori.
-
Come temevo... la documentazione di QThread e' sbagliata dai tempi di Qt4, tutti si lamentano ma nessuno mai la cambia, ti consiglia di fare cose sbagliate. La spiegazione di come usarli correttamente la trovi qui: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ ma, in pratica, nel 99.9% dei casi QThread non va subclassato. Crea una classe che eredita da QObject che faccia il lavoro e usa
moveToThread
-
@VRonin
ok grazie mille per le dritte. Ora mi studio meglio i threads ;)