Legal way for blocking signals and slots and passing by reference
-
I currently have a main window class containing a tcp socket subclass and a socket thread (does all of the ready read parsing) that uses moveToThread. My issue is that I would like to get the information of the connected client (if connected) on closeEvent in the main window and store it to an ini file.
For example:
@
// create the data socket
// this is a subclass of a QTcpSocket
// all socket communications will be done within a thread
_socket = new DataSocket();
_socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
qRegisterMetaTypeQAbstractSocket::SocketState("QAbstractSocket::SocketState");
connect(_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this, SLOT(connectionStateChanged(QAbstractSocket::SocketState)));
connect(_socket, SIGNAL(error(QString)), this, SLOT(error(QString)));
connect(this, SIGNAL(connectToServer(QString,uint)), _socket, SLOT(connectToServer(QString,uint)));
connect(this, SIGNAL(disconnectFromServer()), _socket, SLOT(disconnectFromServer()));_socketThread = new QThread(this);
_socket->moveToThread(_socketThread);
_socketThread->start();
@I do not believe it is legal to simply do this in the close event since the object is in another thread:
@
// close event
void MasterView::closeEvent(QCloseEvent *){
// save all settings
saveSettings();// kill the socket thread if it is still running if (_socketThread->isRunning()){ _socketThread->quit(); }
}
// save all settings
void MasterView::saveSettings(){
// save the last ip address
if (_socketState == QAbstractSocket::ConnectedState){
_settingsIni->write("Connection", "LastIP", _socket->peerAddress().toString());
_settingsIni->write("Connection", "LastPort", QString::number(_socket->peerPort()));
} else {
// clear the connection information
_settingsIni->removeKey("Connection", "LastIP");
_settingsIni->removeKey("Connection", "LastPort");
}
}
@Getting the socket state is simple enough by just hooking up the connection state change event to the main window and just saving the state as it changes (in the example, that would be stored in _socketState).
The only two lines I don't think are valid are the ones getting the peer address and peer port due to the _socket object living in another thread from the moveToThread...
@
_settingsIni->write("Connection", "LastIP", QVariant(_socket->peerAddress()));
_settingsIni->write("Connection", "LastPort", QVariant(_socket->peerPort()));
@The only other way I can think of getting this information is creating a blocking signal/slot for the main window to the socket thread that passes a QString (ip address) by reference and an unsigned int (port) by reference to the thread, and just filling the objects from the socket thread.
For example:
@
connect(this, SIGNAL(peerInformation(QString&,uint&)), _socket, SLOT(peerInformation(QString&,uint&)), Qt::BlockingQueuedConnection);
@I have never really ever needed a blocking signal / slot before between threads, so I am curious what the best way to do this would be, or if there is a better way to gather this information with out using global data? Or am I thinking about this all wrong?
Edt: This is the way I have tried, and seems to work okay
@
// save the last ip address
if (_socketState == QAbstractSocket::ConnectedState){
QString ipAddress;
unsigned int portNumber;
QMetaObject::invokeMethod(_socket, "peerInformation", Qt::BlockingQueuedConnection,
Q_ARG(QString&, ipAddress), Q_ARG(unsigned int&, portNumber));
_settingsIni->write("Connection", "LastIP", ipAddress);
_settingsIni->write("Connection", "LastPort", QString::number(portNumber));
} else {
// clear the connection information
_settingsIni->removeKey("Connection", "LastIP");
_settingsIni->removeKey("Connection", "LastPort");
}
@ -
Hi,
I'd say that your use of invokeMethod() is already the best way to handle this.