I have a Qt application written in PySide (Qt Python binding). This application has a GUI thread and many different QThreads that are in charge of performing some heavy lifting - some rather long tasks. As such long task sometimes gets stuck (usually because it is waiting for a server response), the application sometimes freezes.
我有一个Qt应用程序写在PySide (Qt Python绑定)。这个应用程序有一个GUI线程和许多不同的QThreads,它们负责执行一些繁重的任务——一些相当长的任务。由于如此长的任务有时会被卡住(通常是因为等待服务器响应),应用程序有时会冻结。
I was therefore wondering if it is safe to call QCoreApplication.processEvents()
"manually" every second or so, so that the GUI event queue is cleared (processed)? Is that a good idea at all?
因此,我想知道调用QCoreApplication.processEvents()是否安全“手动”每秒钟左右,这样GUI事件队列就被清除(处理)了吗?这是个好主意吗?
2 个解决方案
#1
1
It's safe to call QCoreApplication.processEvents() whenever you like. The docs explicitly state your use case:
可以随时调用QCoreApplication.processEvents()。文档明确说明了您的用例:
You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file).
当程序忙于执行长操作(例如复制文件)时,可以偶尔调用此函数。
There is no good reason though why threads would block the event loop in the main thread, though. (Unless your system really can't keep up.) So that's worth looking into anyway.
不过,为什么线程会在主线程中阻塞事件循环,这是没有好的理由的。(除非你的系统真的跟不上。)不管怎样,这是值得研究的。
#2
0
A couple of hints people might find useful:
人们可能会发现一些有用的提示:
A. You need to beware of the following:
答:你需要注意以下几点:
-
Every so often the threads want to send stuff back to the main thread. So they post an event and call processEvents
每一个线程都希望将内容发送回主线程。因此他们发布了一个事件并调用processEvents。
-
If the code runs from the event also calls processEvents then instead of returning to the next statement, python can instead dispatch a worker thread again and that can then repeat this process.
如果从事件中运行的代码也调用processEvents,而不是返回到下一个语句,那么python可以重新调度一个工作线程,然后再重复这个过程。
The net result of this can be hundreds or thousands of nested processEvent statements which can then result in a recursion level exceeded error message.
它的最终结果可能是数百或数千个嵌套的processEvent语句,它们可以导致递归级别超过错误消息。
Moral - if you are running a multi-threaded application do NOT call processEvents in any code initiated by a thread which runs in the main thread.
如果您正在运行一个多线程应用程序,那么在任何由主线程运行的线程发起的代码中,都不要调用processEvents。
B. You need to be aware that CPython has a Global Interpreter Lock (GIL) that limits threads so that only one can run at any one time and the way that Python decides which threads to run is counter-intuitive. Running process events from a worker thread does not seem to do what it says on the can, and CPU time is not allocated to the main thread or to Python internal threads. I am still experimenting, but it seems that putting worker threads to sleep for a few miliseconds allows other threads to get a look in.
您需要注意的是,CPython有一个全局解释器锁(GIL),它限制线程,以便只有一个线程可以在任何时间运行,而Python决定运行哪个线程的方式是违反直觉的。从一个工作线程运行进程事件似乎不像它在can上说的那样,而CPU时间没有分配给主线程或Python内部线程。我还在做实验,但似乎让工作线程休眠几毫秒就可以让其他线程进入状态。
#1
1
It's safe to call QCoreApplication.processEvents() whenever you like. The docs explicitly state your use case:
可以随时调用QCoreApplication.processEvents()。文档明确说明了您的用例:
You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file).
当程序忙于执行长操作(例如复制文件)时,可以偶尔调用此函数。
There is no good reason though why threads would block the event loop in the main thread, though. (Unless your system really can't keep up.) So that's worth looking into anyway.
不过,为什么线程会在主线程中阻塞事件循环,这是没有好的理由的。(除非你的系统真的跟不上。)不管怎样,这是值得研究的。
#2
0
A couple of hints people might find useful:
人们可能会发现一些有用的提示:
A. You need to beware of the following:
答:你需要注意以下几点:
-
Every so often the threads want to send stuff back to the main thread. So they post an event and call processEvents
每一个线程都希望将内容发送回主线程。因此他们发布了一个事件并调用processEvents。
-
If the code runs from the event also calls processEvents then instead of returning to the next statement, python can instead dispatch a worker thread again and that can then repeat this process.
如果从事件中运行的代码也调用processEvents,而不是返回到下一个语句,那么python可以重新调度一个工作线程,然后再重复这个过程。
The net result of this can be hundreds or thousands of nested processEvent statements which can then result in a recursion level exceeded error message.
它的最终结果可能是数百或数千个嵌套的processEvent语句,它们可以导致递归级别超过错误消息。
Moral - if you are running a multi-threaded application do NOT call processEvents in any code initiated by a thread which runs in the main thread.
如果您正在运行一个多线程应用程序,那么在任何由主线程运行的线程发起的代码中,都不要调用processEvents。
B. You need to be aware that CPython has a Global Interpreter Lock (GIL) that limits threads so that only one can run at any one time and the way that Python decides which threads to run is counter-intuitive. Running process events from a worker thread does not seem to do what it says on the can, and CPU time is not allocated to the main thread or to Python internal threads. I am still experimenting, but it seems that putting worker threads to sleep for a few miliseconds allows other threads to get a look in.
您需要注意的是,CPython有一个全局解释器锁(GIL),它限制线程,以便只有一个线程可以在任何时间运行,而Python决定运行哪个线程的方式是违反直觉的。从一个工作线程运行进程事件似乎不像它在can上说的那样,而CPU时间没有分配给主线程或Python内部线程。我还在做实验,但似乎让工作线程休眠几毫秒就可以让其他线程进入状态。