我有以下情况。
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"
...
}
答案 0 :(得分:5)
当发出QTcpSocket
信号connected()
时,确实会立即触发您的广告位。
但是,当您尝试将该套接字连接到某个地方时,connected()
不会被发出。
文档写道:
在调用connectToHost()之后发出此信号 并且已成功建立连接。
建立连接需要一个事件循环。
答案 1 :(得分:1)
建立连接是异步发生的(读取connectToHost
将在它甚至检查连接是否已建立之前立即返回)并将使用事件触发的信号通知您的代码
这些事件仅在事件循环中或当您调用WaitForConnect时处理(这将调整它自己的偶数循环仅处理这些事件)
这意味着你获得的序列是完全正常的
答案 2 :(得分:0)
我不认为你可以在不引入新线程的情况下做到这一点,只有解决方案似乎是你的解决方案。
或者使用DirectConnection而不是将其留空(这是AutomaticConnection,在您的情况下是QueuedConnection)可能是一个解决方案。但我不认为它会起作用,因为你需要等待才能运行那个插槽。我不确定,试一试。