c++ - 当信号再次触发时第二次调用从 Qt Slot 执行的函数时会发生什么?

标签 c++ qt

这是我的情况。

我正在编写一个 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 从不理所当然地这样做。允许信号和槽重新进入。

行为取决于有效连接类型:

  1. Qt::DirectConnection - 连接就像通过函数指针立即调用一样。 当信号返回时,槽已经完成执行。实际上,就好像 signal() 的实现只是简单地包含了所有槽调用:

    signal(params) { slot(params); ... }
    
  2. Qt::QueuedConnection - 连接就像通过 exec() 中的函数指针调用一样:

    signal(params) { exec.add(slot, params); ... }
    

    然后 exec(QEventLoop::execQCoreApplication::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/

相关文章:

c++ - Linux下文件读取方式不同? C++

c++ - 涉及私有(private)继承的 C 风格向上转型和向下转型

delphi - Qt 或 Delphi...如果您要选择其中之一?

c++ - VideoOutput QML 的自定义源属性

c++ - 根据度数对多项式项进行排序

java - 如何在 Qt for android 上获取应用程序参数

c++ - std::unordered_set 的 std::unordered_map facade - 怎么样?

qt - QLayout 可以隐藏而不是调整 QWidget 的大小吗?

c++ - 如何停止有关未使用的私有(private)字段的警告?

c++ - 使用 Qt 线程的最小示例?