You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

每秒采样PLC数字输入致PYQT GUI卡顿,求解决方案

解决PyQt读取Omron PLC时GUI卡顿的问题

问题根源分析

你的代码存在两个核心问题:

  • 定时器逻辑混乱:每次调用read_DI都会新建QTimer实例,还递归绑定自身,导致定时器重复创建且逻辑冲突,同时PLC读取操作直接在主线程执行,阻塞GUI事件循环。
  • 主线程被IO操作阻塞:PLC读取属于IO密集型操作,在定时器回调中执行会占用主线程资源,导致GUI无法及时响应用户操作(如拖动窗口)。

具体解决方案

1. 修正定时器逻辑,避免重复创建

将定时器初始化移至类的构造函数中,仅创建一次,去掉递归调用的错误逻辑:

class YourPLCWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 仅初始化一次定时器
        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.read_DI)
        self.timer.start()

    def read_DI(self):
        # 这里仅保留PLC读取逻辑
        # 示例:假设使用Omron通信库读取DI值
        # di_values = plc.read_discrete_inputs(start_address, count)
        # 注意:后续更新GUI需确保在主线程执行

2. 用线程分离PLC读取操作

把IO密集型的PLC读取放到独立线程中,彻底避免阻塞主线程:

from PyQt5 import QtCore, QtWidgets

class PLCReaderThread(QtCore.QThread):
    # 定义信号,用于传递读取到的DI值到主线程
    di_values_ready = QtCore.pyqtSignal(list)

    def run(self):
        # 初始化PLC连接(仅执行一次)
        # plc = OmronFinsClient(host="plc_ip", port=9600)
        # plc.connect()
        while True:
            # 批量读取DI值
            # di_values = plc.read_bits("D0", 16)  # 示例读取16个DI点
            di_values = [True, False, True, False]  # 模拟数据
            self.di_values_ready.emit(di_values)
            # 线程内等待1秒,替代定时器
            self.sleep(1)

class YourPLCWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        # 启动PLC读取线程
        self.plc_thread = PLCReaderThread()
        self.plc_thread.di_values_ready.connect(self.update_gui)
        self.plc_thread.start()

    def update_gui(self, di_values):
        # 在主线程更新GUI组件(如复选框、指示灯)
        # for idx, value in enumerate(di_values):
        #     self.di_indicators[idx].setChecked(value)
        pass

    def closeEvent(self, event):
        # 窗口关闭时正确停止线程,避免资源泄漏
        self.plc_thread.quit()
        self.plc_thread.wait()
        event.accept()

3. 优化PLC读取性能

  • 批量读取:一次性读取所有需要的DI点,避免多次IO请求
  • 缓存对比:仅当DI值发生变化时才更新GUI,减少不必要的界面刷新
  • 选用高效库:优先选择性能更优的Omron PLC通信库(如omron_fins)

关键注意事项

  • 永远不要在子线程中直接操作GUI组件,必须通过信号槽机制传递数据到主线程更新
  • 线程启动后,务必在窗口关闭时正确停止并回收线程资源
  • 若需动态启停读取逻辑,可给线程添加控制信号(如start_reading、stop_reading)

内容的提问来源于stack exchange,提问作者עומר דגן

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:13:18