例如,我很难理解发生了什么。两个不同的信号连接到两个不同的插槽,当一个插槽未完成时,将发出其他插槽的信号(对于直接连接到各自信号的两个插槽),其中应用程序只有“一个”线程。
这是来自QT官方文档:
Direct Connection: The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.
Queued Connection: The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
与排队连接不同,它表示“立即”用于直接连接。这是否意味着,如果在第一个插槽尚未完成时发出第二个信号,则第一个插槽将被中断,并且即使应用程序是单线程应用程序,它也会与第二个插槽同时运行?如果是这样,为什么我没有看到任何应该使用互斥锁来锁定两个槽都可以访问的变量的警告。
也许我误解了整个“直接”和“排队”连接。
最佳答案
我认为您误解的不是排队版本和直接版本,而是整个信号/槽机制。当您同步或异步需要知道应用程序的另一部分(可能是单线程或多线程)何时完成其工作时,信号/槽系统是回调问题的更优雅的解决方案。
直接/排队
在深入了解基础知识之前,让我们先解决这个问题。
- 如果是直接连接,您的代码总是在单个线程上执行,无论槽是否在不同的线程上运行。 (在大多数情况下,这是一个非常糟糕的主意)
- 如果连接排队并且插槽在同一个线程内运行,它的行为完全就像一个直接连接。如果插槽在不同的线程上运行,则插槽将在其运行所在的适当线程上下文中执行,从而使代码执行成为多线程的。
- 如果连接是默认的auto,那么它会选择合适的连接类型。
现在有一种方法可以强制您的代码执行跳转到另一个线程的槽中,那就是调用一个方法:
QMetaObject::invokeMethod( pointerToObject*, "functionName", Qt::QueuedConnection);
基础知识
那么让我们快速回顾一下信号/槽机制。系统中有三个参与者:信号、槽和 connect()
信号基本上是说“嘿!我完成了”的消息。插槽是代码中进行后处理的地方,因此一旦信号完成,您就可以在代码的插槽部分执行某些操作。
connect() 是一种组织发生在何处以及出于何种原因发生的事情的方法。信号/槽的执行顺序与您的代码执行顺序相同。先到先得,因为你确实提到了单线程。在不同的多线程环境中。老实说,执行顺序无关紧要,如果您尝试使用信号/槽并需要保证执行顺序,那么您的应用程序设计是错误的。理想情况下,您使用信号/槽机制的方式与函数式编程的工作方式相同,您将消息传递给下一个实例以处理数据。
废话不多说了,让我们来看看一些实际的细节:
signals:
void a();
void b();
slots:
void sa();
void sb();
案例一
connect( a -> sa ); // Simplified Notation. Connect signal a to slot sa
connect( b -> sb );
:: emit a(); -> sa is executed
:: emit b(); -> sb is executed
案例二
connect ( a -> sa );
connect ( a -> sb );
connect ( b -> sb );
:: emit a(); -> sa & sb are executed
:: emit b(); -> sb is executed
我想这应该说清楚了。如果您还有任何问题,请告诉我
关于multithreading - QT 信号和插槽在单线程应用程序中的直接连接行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38376840/