QThread结合pyqtgraph无性能提升问题咨询
Hey there! Let's figure out why your threaded pyqtgraph setup isn't giving you the CPU performance boost you're hoping for, and walk through fixes that should help.
1. You're probably updating the GUI directly from the child thread
PyQt/PySide enforces a strict rule: all GUI operations must happen in the main thread. If your threaded code is calling pyqtgraph plotting methods (like plot() or clear()) directly from the worker thread, you're not just breaking Qt's thread safety rules—you're adding unnecessary cross-thread synchronization overhead that can keep CPU usage high (or even make it worse).
Fix it with signals & slots:
Move only your data-fetching logic to the child thread, then use Qt signals to send the data to the main thread for plotting. Here's a simplified example:
from PyQt5.QtCore import QThread, QObject, pyqtSignal import psutil class DataWorker(QObject): # Signal to send fetched data back to main thread new_data = pyqtSignal(float) _is_running = True def run(self): while self._is_running: # Only do the data fetch work here (no GUI calls!) cpu_val = psutil.cpu_percent(interval=0.1) self.new_data.emit(cpu_val) # Use Qt's thread sleep instead of time.sleep to respect event loops QThread.msleep(100) def stop(self): self._is_running = False # In your main window class class MultiPlotWindow(QMainWindow): def __init__(self): super().__init__() # Initialize your pyqtgraph widgets here self.cpu_plot = self.setup_pyqtgraph_plot() # Set up the worker thread self.worker = DataWorker() self.thread = QThread() self.worker.moveToThread(self.thread) # Connect signals: data from worker triggers GUI update self.worker.new_data.connect(self.update_cpu_plot) self.thread.started.connect(self.worker.run) # Start the thread self.thread.start() def update_cpu_plot(self, cpu_value): # This runs in the main thread - safe to update pyqtgraph here # Use setData() instead of re-plotting for better performance self.cpu_plot.setData([cpu_value], clear=True) def closeEvent(self, event): # Clean up the thread properly on window close self.worker.stop() self.thread.quit() self.thread.wait() event.accept()
2. Your data-fetching task is too fast to benefit from threading
Threads shine when you have long-running tasks (like heavy computations, slow IO, or waiting for external data). If your current data-fetching logic only takes a few milliseconds to complete, moving it to a thread won't reduce CPU usage—because the bottleneck wasn't blocking the main thread in the first place.
Verify this:
Add timing to your non-threaded timer callback to see how long data fetching takes:
import time def timer_callback(self): start_time = time.time() # Your existing data fetch code data = self.get_data() print(f"Data fetch took: {(time.time() - start_time)*1000:.2f}ms") self.update_plots(data)
If the time is under ~10ms, threading won't help here—you'll need to optimize the GUI rendering instead.
3. You're using QThread incorrectly
Some tutorials teach subclassing QThread and overriding run(), but this can lead to mistakes if you don't manage the thread's event loop properly. Using time.sleep() instead of Qt's thread-safe sleep methods can also cause unnecessary CPU wakeups.
Best practices for QThread:
- Always move a
QObjectworker to a QThread (like the example above) instead of subclassing QThread directly. - Use
QThread.msleep()/usleep()instead oftime.sleep()to let the thread respect Qt's event system. - Always clean up threads (call
quit()+wait()) when closing the window to avoid zombie threads.
4. The CPU overhead is coming from pyqtgraph rendering
If you have multiple plots updating frequently, the CPU usage might be from GUI rendering (which happens in the main thread, so threads can't help here). Try these optimizations:
- Reduce the refresh rate (if 0.1s is too frequent, try 0.2s).
- Use
PlotDataItem.setData()instead of callingplot()every time—this reuses existing plot items instead of creating new ones. - Disable unnecessary plot features (like auto-scaling if you don't need it, or hide grid lines temporarily).
内容的提问来源于stack exchange,提问作者Misael Alarcon

