sg_后台线程运行函数:.perform_long_operation(func, callback)
在 PySimpleGUI 中,.perform_long_operation() 是一个专门用于 后台长时间运行任务 的方法,它会自动处理线程的创建和回调,比手动使用 start_thread() 更简洁。以下是使用 .perform_long_operation() 重写的示例:
完整代码(使用 .perform_long_operation())
import PySimpleGUI as sg
import math
import time
def calculate_sqrt_sum(window, stop_event):
"""后台计算函数(会被自动放到线程中运行)"""
total = 10_000_000
sum_result = 0.0
start_time = time.time()
try:
for i in range(1, total + 1):
if stop_event.is_set(): # 检查是否被取消
return None # 返回None表示计算被取消
sum_result += math.sqrt(i)
# 每100万次更新一次进度
if i % 1_000_000 == 0 or i == total:
progress = i / total * 100
elapsed = time.time() - start_time
window.write_event_value('-UPDATE-', (progress, sum_result, elapsed))
return (sum_result, time.time() - start_time) # 返回结果和总用时
except Exception as e:
window.write_event_value('-ERROR-', str(e))
return None
def main():
stop_event = sg.ThreadSafeEvent() # 线程安全的事件对象
layout = [
[sg.Text('计算1000万以内平方根之和')],
[sg.ProgressBar(100, key='-PROGRESS-', size=(30, 20))],
[sg.Multiline('', size=(40, 5), key='-OUTPUT-', autoscroll=True)],
[sg.Text('结果:'), sg.Input('', key='-RESULT-', disabled=True)],
[sg.Button('开始'), sg.Button('停止'), sg.Button('退出')]
]
window = sg.Window('多线程计算示例', layout, finalize=True)
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, '退出'):
stop_event.set() # 通知线程停止
break
elif event == '开始':
window['-PROGRESS-'].update(0)
window['-RESULT-'].update('')
window['-OUTPUT-'].update('计算中...\n')
stop_event.clear()
window['开始'].update(disabled=True)
window['停止'].update(disabled=False)
# 使用 perform_long_operation 启动后台任务
window.perform_long_operation(
lambda: calculate_sqrt_sum(window, stop_event), # 要执行的任务
'-COMPLETED-' # 任务完成后的回调事件名
)
elif event == '停止':
stop_event.set()
window['-OUTPUT-'].print('\n尝试停止计算...')
window['停止'].update(disabled=True)
elif event == '-UPDATE-':
progress, result, elapsed = values[event]
window['-PROGRESS-'].update(int(progress))
window['-OUTPUT-'].print(f'进度: {progress:.1f}%, 已用时: {elapsed:.2f}秒')
elif event == '-COMPLETED-':
result = values[event] # 获取后台任务的返回值
if result is None:
window['-OUTPUT-'].print('\n计算被取消或出错')
else:
sum_result, elapsed = result
window['-RESULT-'].update(f'{sum_result:.2f}')
window['-OUTPUT-'].print(f'\n计算完成! 结果: {sum_result:.2f}, 总用时: {elapsed:.2f}秒')
window['开始'].update(disabled=False)
elif event == '-ERROR-':
sg.popup_error(f'错误: {values[event]}')
window['开始'].update(disabled=False)
window.close()
if __name__ == '__main__':
main()
关键改进说明
-
.perform_long_operation()的作用:- 自动在后台线程中执行
calculate_sqrt_sum() - 任务完成后触发
-COMPLETED-事件,并通过values[event]返回结果 - 无需手动管理线程的启动和停止
- 自动在后台线程中执行
-
线程安全的事件对象:
- 使用
sg.ThreadSafeEvent()替代threading.Event(),确保线程安全
- 使用
-
简化的流程:
- 点击"开始" → 启动后台任务 → 任务自动在独立线程中运行
- 任务完成或取消后,通过
-COMPLETED-事件通知主线程
-
取消任务的处理:
- 设置
stop_event后,后台任务会在下一次循环检查时退出 - 返回
None表示任务被取消
- 设置
对比 .start_thread() 的优势
| 特性 | .perform_long_operation() |
.start_thread() |
|---|---|---|
| 线程管理 | 自动处理 | 需手动管理 |
| 回调机制 | 内置(通过事件名) | 需手动写事件处理 |
| 返回值传递 | 支持 | 需额外事件传递 |
| 代码复杂度 | 更低 | 较高 |
适用场景
-
推荐使用
.perform_long_operation():- 需要简单后台任务+回调的场景
- 希望减少线程管理代码
- 需要直接获取返回值
-
保留
.start_thread()的场景:- 需要同时运行多个独立线程
- 需要更精细的线程控制(如守护线程)
这个版本更符合 PySimpleGUI 的设计理念,代码更简洁且易于维护。

浙公网安备 33010602011771号