我确实有一个奇怪的问题。我有一个用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'])
答案 0 :(得分:0)
通常我会通过在正在运行的循环中调用QtGui.qApp.processEvents()
来解决这类问题。
例如,如果我有for
循环处理大量信息(有时会使窗口无响应),我会在循环结束时调用QtGui.qApp.processEvents()
。此调用通过处理所有事件使GUI响应。换句话说,这将更新窗口。
出现问题,我不知道您的代码中的哪个位置窗口没有响应,我认为processEvents()
对您有用。
答案 1 :(得分:0)
假设第二个进程是正确的,我想知道你的主机是直接从辅助线程(从套接字读取)直接接收消息并直接放入GUI。您只能从主线程操作GUI,因此这可能是一个问题。
答案 2 :(得分:0)
我找到了瓶颈。它与套接字通信相关,也不发出信号。连接的插槽使用QTextEdit.insertHtml(msg)
将其打印到文本字段。此方法调用可用于不显示。
我现在将尝试删除该视图并添加一个TableView。然后将消息附加到附加的模型。我希望这会更好 - 或者有更好的方法吗?