pysimplegui之使用多线程,避免程序卡死

这个问题我也遇到过,就是还需要一个while循环的时候,放到gui本身循环会卡死,这时候就需要启动多线程

 

 

需要“长时间”的操作

如果您是 Windows 用户,您会在其标题栏中看到窗口显示“未响应”,然后很快会出现一个 Windows 弹出窗口,指出“您的程序已停止响应”。好吧,如果您愿意,您也可以使该消息和弹出窗口出现!您需要做的就是在您的事件循环中执行一个花费“太长”(即几秒钟)的操作。

你有几个选择来处理这个问题。如果您的操作可以分解成更小的部分,那么您可以Window.Refresh()偶尔调用以避免出现此消息。例如,如果您正在运行一个循环,请将该调用与您的其他工作一起放入。这将使 GUI 保持快乐,Window 不会抱怨。

另一方面,如果您的操作不受您的控制,或者您无法添加Refresh调用,那么您可以使用的下一个选项是将您的长操作移动到一个线程中。

“老路”

有几个演示程序可供您查看如何执行此操作。你基本上把你的工作放到一个线程中。当线程完成时,它通过队列发送消息来告诉 GUI。事件循环将运行一个计时器,该计时器设置为一个值,该值表示您希望您的 GUI 对工作完成的“响应”程度。

“新方式”—— Window.write_event_value

这个截至 2020 年 7 月目前仅在 tkinter 端口中可用的新功能令人兴奋,它代表了在 PySimpleGUI 中处理多线程的未来方式(或者希望如此)。

以前,使用队列,您的事件循环将轮询来自线程的传入消息。

现在,线程可以直接将事件注入到 Window 中,以便它显示在window.read()调用中。这允许您的事件循环“挂起”,等待正常的窗口事件以及线程生成的事件。

您可以在此演示中看到此新功能的实际效果:Demo_Multithreaded_Write_Event_Value.py

这是您的检查和教育计划。不再轮询线程事件真是太好了。

import threading
import time
import PySimpleGUI as sg
"""
Threaded Demo - Uses Window.write_event_value communications
Requires PySimpleGUI.py version 4.25.0 and later
This is a really important demo to understand if you're going to be using multithreading in PySimpleGUI.
Older mechanisms for multi-threading in PySimpleGUI relied on polling of a queue. The management of a communications
queue is now performed internally to PySimpleGUI.
The importance of using the new window.write_event_value call cannot be emphasized enough. It will hav a HUGE impact, in
a positive way, on your code to move to this mechanism as your code will simply "pend" waiting for an event rather than polling.
Copyright 2020 PySimpleGUI.org
"""
THREAD_EVENT = '-THREAD-'
cp = sg.cprint
def the_thread(window):
"""
The thread that communicates with the application through the window's events.
Once a second wakes and sends a new event and associated value to the window
"""
i = 0
while True:
time.sleep(1)
window.write_event_value('-THREAD-', (threading.current_thread().name, i)) # Data sent is a tuple of thread name and counter
cp('This is cheating from the thread', c='white on green')
i += 1
def main():
"""
The demo will display in the multiline info about the event and values dictionary as it is being
returned from window.read()
Every time "Start" is clicked a new thread is started
Try clicking "Dummy" to see that the window is active while the thread stuff is happening in the background
"""
layout = [ [sg.Text('Output Area - cprint\'s route to here', font='Any 15')],
[sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)],
[sg.T('Input so you can see data in your dictionary')],
[sg.Input(key='-IN-', size=(30,1))],
[sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ]
window = sg.Window('Window Title', layout, finalize=True)
while True: # Event Loop
event, values = window.read()
cp(event, values)
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event.startswith('Start'):
threading.Thread(target=the_thread, args=(window,), daemon=True).start()
if event == THREAD_EVENT:
cp(f'Data from the thread ', colors='white on purple', end='')
cp(f'{values[THREAD_EVENT]}', colors='white on red')
window.close()
if __name__ == '__main__':
main()

多线程程序

在讨论多线程主题时,准备了另一个演示,展示了如何在程序中运行多个线程,这些线程都与事件循环通信,以便在 GUI 窗口中显示某些内容。回想一下,对于 PySimpleGUI(至少是 tkinter 端口),您不能在主程序线程以外的线程中进行 PySimpleGUI 调用。

这些线程程序的关键是从线程到事件循环的通信。为这些演示选择的机制使用 Python 内置queue模块。事件循环轮询这些队列以查看是否从要显示的线程之一发送了某些内容。

您会发现显示多个线程与单个 GUI 通信的演示被称为:

Demo_Multithreaded_Queued.py

对于普通的 PySimpleGUI(基于 tkinter)再次发出警告- 您的 GUI 绝不能作为除主程序线程之外的任何东西运行,并且没有线程可以直接调用 PySimpleGUI 调用

posted @   菩提浪子  阅读(3031)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示

目录导航