Question

I have a following situatuion.

  • 2 Socket objects are created in the main in a for loop (the original problem has 1000 objects). Upon creation the start() method is invoked.
  • start() creates a QTcpSocket which tries to connect to some host.
  • Socket has slots which catch the connected() signal from QTcpSocket and print some debug output

What happens is that chronologically first ALL the Socket objects are created after which the sockets are started. Here is an example output of debug options:

1. Created Socket object 1
2. Invoked Socket object 1 start()
3. Created Socket object 2
4. Invoked Socket object 2 start()
5. Socket object 1 TcpSocket Connected
6. Socket object 2 TcpSocket Connected

Code:

//main.cpp
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    for (int i=0; i<10; i++)
    {
        Socket *socket = new Socket();
        qDebug() << "Socket object created";
        socket->Start();
    }
    return a.exec();
}

//socket.cpp
Socket::Socket(QObject *parent)
    : QObject(parent)
{}

void Socket::Start()
{
    qDebug()<<"Start method invoked";
    socket = new QTcpSocket(this);

    connect(socket,SIGNAL(connected()), this, SLOT(on_connect()), Qt::DirectConnection);
    socket->connectToHost("192.168.5.5",12345);
}

void Socket::on_connect()
{
    QTcpSocket* socket = qobject_cast<QTcpSocket *>(QObject::sender());
    qDebug() << socket->socketDescriptor() <<  " Connected.";
}

This is not the behavior I expected because the documentation states:

When a signal is emitted, the slots connected to it are usually executed immediately, just like a normal function call. When this happens, the signals and slots mechanism is totally independent of any GUI event loop.

Question:

How to ensure the slots are executed "immediately" (not only after the loop in the main finishes) when the signal is emitted?


The only available solution (without introducing new threads) i currently see:

Drop the use of signals and slots in this case, and implement everything in the start method. Something like this:

Socket::start(){
...
if(!tcpsocket->waitForConnected(200)) qDebug() << "Socket object X TcpSocket Connected"
...
}
Was it helpful?

Solution 2

establishing the connection happens asynchronously (read connectToHost will return immediately before it even checks whether the connection has already been established) and will notify your code using the signals that are triggered by events

these events are handled only in the event loop or when you call WaitForConnect (which will spin up it's own even loop only handling those events)

this means that the sequence you get is perfectly normal

OTHER TIPS

Your slot is indeed triggered immediately when QTcpSocket's signal connected() is emitted.

However, connected() is not emitted the moment you try to connect that socket to somewhere.

The documentation writes:

This signal is emitted after connectToHost() has been called and a connection has been successfully established.

The establish of a connection requires an event loop.

I don't think you can do that without introducing new threads, only solution is seems your solution.

Or using DirectConnection instead of leaving it empty (Which is AutomaticConnection and which is QueuedConnection in your case) may be a solution. But I don't think that it will work because you need to wait in order to run that slot. I'm not sure, just give it a try.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top