Qt信号和插槽机制被主循环阻塞

The*_*eer 0 qt event-loop signals-slots qt-signals

我有一个以下的情况.

  • Socketfor循环中创建了2个对象(原始问题有1000个对象).在创建时,start()调用该方法.
  • start()创建一个QTcpSocket尝试连接到某个主机的.
  • Socket有插槽connected()从QTcpSocket 捕获信号并打印一些调试输出

所发生的事情是按时间顺序首先Socket创建所有对象,然后启动套接字.以下是调试选项的示例输出:

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
Run Code Online (Sandbox Code Playgroud)

码:

//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.";
}
Run Code Online (Sandbox Code Playgroud)

这不是我期望的行为,因为文档说明:

发出信号时,通常会立即执行与其连接的插槽,就像正常的函数调用一样.发生这种情况时,信号和插槽机制完全独立于任何GUI事件循环.

问题:

如何确保在发出信号时"立即"(不仅在主要完成循环之后)执行插槽?


唯一可用的解决方案(不引入新线程)我目前看到:

在这种情况下,不要使用信号和插槽,并实现start方法中的所有内容.像这样的东西:

Socket::start(){
...
if(!tcpsocket->waitForConnected(200)) qDebug() << "Socket object X TcpSocket Connected"
...
}
Run Code Online (Sandbox Code Playgroud)

yzn*_*pku 5

当发出QTcpSocket信号时,确实会立即触发您的插槽connected().

但是,connected()在您尝试将该套接字连接到某个位置时,不会发出这种情况.

文档写道:

在调用connectToHost()并成功建立连接后发出此信号.

建立连接需要事件循环.