0

我有以下情况。

  • 在主循环Socket中创建了2 个对象(原始问题有 1000 个对象)。在创建时调用该方法。forstart()
  • 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

代码:

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

这不是我所期望的行为,因为文档指出:

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

问题

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


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

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

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

3 回答 3

5

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

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

文档写道:

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

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

于 2013-10-25T08:44:38.670 回答
1

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

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

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

于 2013-10-25T09:02:16.230 回答
0

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

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

于 2013-10-25T08:41:27.903 回答