长期运行后,Python UI无响应

时间:2014-02-19 16:20:12

标签: python pyqt multiprocessing pyside

我确实有一个奇怪的问题。我有一个用Python编写的双进程应用程序和用于GUI的PySide。

GUI在第一个线程中运行,并在其中运行测量状态机的第二个进程(以防止python GIL)。一旦启动,此FSM通过套接字将消息发送到主机应用程序(用于通信)。此FSM执行时间通常很长(5小时)。

现在的问题是主机应用程序无论如何都没有响应。用户界面不再更新(第二个进程的已接收消息不再显示),而Windows则表示该应用程序不具有响应性。第二个过程仍然可以正常工作。

任何人都可以帮我解决这个问题吗?这只适用于运行时间很长的FSM以及FSM中有很多工作要做。这可能是一般的资源问题吗?

编辑: 第一个下面的代码显示了捕获来自第二个进程的消息的线程的run-method。这将调用下面定义的回调。此回调仅发出信号(并使用接收的数据提供它们)以更新UI(例如,记录到UI)。

class RunnerServer(QThread):
    # ...
    def run(self):
        try:
            self._socket.bind((self._host, 0))
            self._port = self._socket.getsockname()[1]
            self._is_started.set()
            while not self._stop_event.is_set():
                try:
                    data = self._socket.recvfrom(2048)[0]
                except socket.error :
                    continue
                if self._callback:
                    o = pickle.loads(data)
                    self._callback(o, *self._args, **self._kwargs)
        except:
            traceback.print_exc()
        finally:
            self._socket.close()


class Controller:
    # ...
    def remote_server_rx_callback(self, message, *args, **kwargs):
        if isinstance(message, RunnerMessage):
            self._sig_log_msg.emit(lmessage.message_type, message.message, message.source
        elif isinstance(message, StatusMessage):
            if message.message_type == StatusType.START:
                self._sig_runner_started.emit()
            elif message.message_type == StatusType.FINISH:
                self._sig_runner_finished.emit()
            elif message.message_type == StatusType.PROGRESS:
                self._sig_runner_update_progress.emit(message.payload['progress'])

3 个答案:

答案 0 :(得分:0)

通常我会通过在正在运行的循环中调用QtGui.qApp.processEvents()来解决这类问题。

例如,如果我有for循环处理大量信息(有时会使窗口无响应),我会在循环结束时调用QtGui.qApp.processEvents()。此调用通过处理所有事件使GUI响应。换句话说,这将更新窗口。

出现问题,我不知道您的代码中的哪个位置窗口没有响应,我认为processEvents()对您有用。

答案 1 :(得分:0)

假设第二个进程是正确的,我想知道你的主机是直接从辅助线程(从套接字读取)直接接收消息并直接放入GUI。您只能从主线程操作GUI,因此这可能是一个问题。

答案 2 :(得分:0)

我找到了瓶颈。它与套接字通信相关,也不发出信号。连接的插槽使用QTextEdit.insertHtml(msg)将其打印到文本字段。此方法调用可用于不显示。

我现在将尝试删除该视图并添加一个TableView。然后将消息附加到附加的模型。我希望这会更好 - 或者有更好的方法吗?