PyQt4:传统的多线程UI信号/插槽机制?

时间:2013-10-21 10:39:34

标签: python multithreading qt thread-safety pyqt

任何使用多线程PyQt4应用程序的人?我只是想知道内置的信号/插槽机制是否与PyQt4框架的QtThread结合使用事件驱动的异步回调是否比标准Python线程(我的代码中设计用于以线程安全的方式处理UI组件)有任何好处。

我正在寻找任何主要的速度或安全问题,任何特定的运行时异常或边缘情况。 (用户界面非常复杂,因此在稍后阶段重写会非常适得其反)。

感谢。

编辑:我意识到这可能意味着复制一些已经存在的PyQt核心功能,但如果它在应用程序中允许更多的灵活性就没问题。

2 个答案:

答案 0 :(得分:0)

如果您没有使用信号和插槽机制并滚动自己的事件循环,那么真正使用Qt / PyQt毫无意义。基本上,您将重新实现框架本身的核心。但我猜这不是你要问的。

如果你能稍微澄清一下你的问题会很好(因为我必须做出一些假设) 但这是交易:

我认为你对信号和插槽机制的作用有点困惑。 (或许不是,原谅我重申一些可能对你来说很明显的东西)。

信号和插槽不会为您实现线程(因此使用信号/插槽比标准Python线程有任何好处的问题是没有意义的)

您可能假设信号槽机制是多线程的,并且信号调用时的槽在新线程中执行。嗯,事实并非如此。

Qt中的信号和插槽机制在Qt中的单个事件循环中运行(由QApplication实现),它本身在单个线程中运行。 因此,信号和插槽不能以任何方式替代多线程。

如果有一个阻塞的插槽,那么它将阻止整个应用程序。 因此,理想情况下,任何阻塞I / O或时间密集型函数都应该位于与UI不同的线程中,并且您的插槽应该开始执行这些线程。 现在是否使用QThread或标准Python线程来实现自己的线程是另一个问题,之前已经在StackOverflow上询问过,但我倾向于将QThreads用于Qt应用程序。

因此,如果您有一个按钮,并且您希望在单击时使用请求库启动文件下载,则会将QPushButton的clicked信号连接到插槽,例如{{1}并且该插槽将启动一个新的QThread,它将负责使用请求下载文件。您可以进一步连接来自QThread的finished()信号,以了解下载何时完成并更新您的UI

(如果这确实是你要问的话,我会添加一个代码示例。所以请澄清你的问题)

答案 1 :(得分:0)

根据您对其他回复的评论:

  

对于模棱两可的抱歉,我在谈论QtThread Slot / Signal   使用内置Python线程的机制与回调。我打算   在事件到达时创建单独的线程(点击等)和   然后使用从新线程到主UI线程的回调   更新UI(主线程中的所有UI逻辑都带有锁以保留它   线程安全。)我知道这可能意味着已经复制了一些   提出PyQt功能,但我觉得这样我会有更多   控制我的应用程序。 (如果允许更多,额外的工作不是问题   应用程序的灵活性。此外,它不是那么多工作)

我想说你所追求的是从你的线程中使用QApplication.postEvent()。使用一些额外的代码,您可以使用它来同步或异步地在主线程中执行任意方法。

我不确定任何一个选项(Qt或Python线程)确实有任何优点或缺点。据我所知,他们仍然持有GIL,这意味着你的程序永远不会真正多线程。 QThread带有一个事件循环,但正如你所说,在你自己的Python线程中编写自己并不难。

您是否考虑过使用多个进程而不是多个线程?虽然启动速度较慢,但​​您可以获得实际并行运行代码的优势。

在一天结束时,我认为你的问题的答案只是个人偏好。我的目的是避免使用QThread,因为如果PyQt \ PySide \ Qt死了,将来可以更容易将应用程序移植到另一个小工具包中(不是很有可能,但我有一个对PyGTK的经验不好所以现在我很谨慎)

编辑:请同时看看这个,因为它有比我给出的答案更好的答案:Threading in a PyQt application: Use Qt threads or Python threads?