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

时间:2013-10-25 08:24:37

标签: qt signals-slots event-loop qt-signals

我有以下情况。

  • Socket循环中的主要内容中创建了2 for个对象(原始问题有1000个对象)。创建后,将调用start()方法。
  • start()创建QTcpSocket,尝试连接到某个主机。
  • Socket具有从QTcpSocket捕获connected()信号并打印一些调试输出的插槽

按时间顺序首先创建所有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

代码:

//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.";
}

这不是我预期的行为,因为documentation表示:

  

发出信号时,通常会连接到它的插槽   立即执行,就像正常的函数调用一样。当这个   发生时,信号和插槽机制完全独立于任何   GUI事件循环。

问题

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


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

在这种情况下放弃使用信号和插槽,并在start方法中实现所有内容。像这样:

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

3 个答案:

答案 0 :(得分:5)

当发出QTcpSocket信号connected()时,确实会立即触发您的广告位。

但是,当您尝试将该套接字连接到某个地方时,connected()不会被发出。

文档写道:

  

在调用connectToHost()之后发出此信号   并且已成功建立连接。

建立连接需要一个事件循环。

答案 1 :(得分:1)

建立连接是异步发生的(读取connectToHost将在它甚至检查连接是否已建立之前立即返回)并将使用事件触发的信号通知您的代码

这些事件仅在事件循环中或当您调用WaitForConnect时处理(这将调整它自己的偶数循环仅处理这些事件)

这意味着你获得的序列是完全正常的

答案 2 :(得分:0)

我不认为你可以在不引入新线程的情况下做到这一点,只有解决方案似乎是你的解决方案。

或者使用DirectConnection而不是将其留空(这是AutomaticConnection,在您的情况下是QueuedConnection)可能是一个解决方案。但我不认为它会起作用,因为你需要等待才能运行那个插槽。我不确定,试一试。