In which thread is a slot executed, and can I redirect it to another thread?

半城伤御伤魂 提交于 2019-12-02 03:42:56

There are two main types of slot in PyQt: ones which are wrapped Qt slots. and ones which are ordinary python callable objects.

The first type includes the built-in slots defined by Qt, plus any user-defined slots decorated with pyqtSlot. These slots will work exactly as documented by Qt, so there are no additional PyQt-specific "rules" that apply to them. By definition, they must be members of a QObject subclass, which in turn means they are part of the Meta Object System. You can therefore explictly check that a slot is of this type by using, e.g. indexOfSlot.

For the second type of slot, PyQt creates an internal proxy object that wraps the python callable and provides the Qt slot required by the signal-slot mechanism. This therefore raises the question of where this proxy object should live. If the callable is owned by an object that inherits QObject, PyQt can automatically move the proxy to the appropriate thread. In pseudo-code, it will do something like this:

if receiver:
    proxy.moveToThread(receiver.thread())

However, if there's no appropriate reveiver, the proxy will just stay in whatever thread it was created in.

It is this latter case that applies to your example. The slot_to_output_something slot is just a module-level function with no owner. PyQt cannot find a receiver associated with it, so the internal proxy will stay in the thread where the connection was made. However, if this slot was moved to become a member of Object_With_A_Signal, it would be called in the main thread. This is because Object_With_A_Signal inherits QObject and the instance of it currently lives in the main thread. This allows PyQt to automatically move the internal proxy to the thread of the appropriate receiver.

So, if you want to control where a slot gets executed, make it a member of a QObject subclass and, if necessary, use moveToThread to explicitly place it in the appropriate thread. In addition, it is probably advisable to apply the pyqtSlot decorator so as to avoid any awkward corner cases (see this answer for details).

PS:

The above "rules" for the second type of slot probably only apply to PyQt - it's unlikely that things will work the same way in PySide. And there's also probably no guarantee that they will work in exactly the same way with all previous or future versions of PyQt. So if you want to avoid unexpected changes of behaviour, it's best to use the pyqtSlot decorator with any slots that are going to be connected between different threads.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!