这是我的情况。
我正在编写一个 TCP 服务器。该服务器将接收来自多个客户端的请求。
我有一个接收信息的类(基于名为 MySocket
的 QTCPSocket)并缓冲它直到所有信息都到达。需要明确的是,客户端一旦检测到它已成功与我的服务器类建立连接,就会发送其信息。客户端和服务器是运行在不同计算机(实际上甚至是不同操作系统)上的独立程序。
当 MySocket
接收到所有数据后,它向服务器控件类发送一个 qt 信号。这是在一个插槽中接收的,该插槽根据其唯一参数执行许多操作。当参数告诉它已收到数据时,它会调用函数 ProcessInformation
。这个函数需要做一些事情,所以它不是即时的。
如果我在服务器上收到新的连接请求,它会保存在 MySocket
的另一个实例中,它会在收到所有数据后再次发出信号。
这是我不确定会发生什么的地方。我相信 Qt Signal-Slot 系统将确保它能正常工作。如果我没记错的话,因为槽函数还没有完成它的运行,第二个信号将被排队,我将得到想要的行为:ProcessInformation
将在它完成完成了它的第一次运行。但是,我不确定,所以我要问:程序在这种情况下的行为如何?所以我可以相应地编程。
由于这是在不同计算机上运行的两个不同程序,并且考虑到我需要测试两个客户端同时发送其数据以查看其效果,我不确定如何测试这种情况。
最佳答案
since the slot function has not completed its run, the second signal will be queued
绝对不会。Qt 从不理所当然地这样做。允许信号和槽重新进入。
行为取决于有效连接类型:
Qt::DirectConnection
- 连接就像通过函数指针立即调用一样。 当信号返回时,槽已经完成执行。实际上,就好像signal()
的实现只是简单地包含了所有槽调用:signal(params) { slot(params); ... }
Qt::QueuedConnection
- 连接就像通过exec()
中的函数指针调用一样:signal(params) { exec.add(slot, params); ... }
然后
exec
(QEventLoop::exec
或QCoreApplication::exec
)执行此操作:exec() { dispatchEvents(); while (!calls.empty()) calls.take_first().invoke(); }
Qt 还支持默认的自动连接,其中有效类型在运行时在信号内确定:
signal(params) {
for (conn: connections)
sameThread = conn.receiver.thread() == currentThread();
if (conn.isDirect || (conn.isAutomatic && sameThread))
conn.slot(params)
else if (conn.isQueued || (conn.isAutomatic && !sameThread))
exec.add(conn.slot, params);
}
因此,如果你使用默认的自动连接类型,并且调用者和接收者在同一个线程中,那么调用信号与直接在接收者对象中调用槽是一样的。如果调用者和接收者在不同的线程中,那么调用信号将始终排队等待控制返回事件循环时执行的调用。
请注意,在 Qt 中,几乎在所有情况下,exec()
都在您的代码运行时(实际上是您的任何代码)都在调用堆栈上。例如。调用堆栈可能如下所示:
MyClass::onButtonClick() // your slot connected to a button's clicked signal
QAbstractButton::clicked() // signal - just a C++ method (!)
QPushButton::event() // the event handler that got the mouse event
QCoreApplication::notify()
... (platform code etc)
QAbstractEventDispatcher::processEvents()
QCoreApplication::exec()
main()
__thread_start()
// C runtime code
关于c++ - 当信号再次触发时第二次调用从 Qt Slot 执行的函数时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51686194/