Kivy应用实现带进度条的后台线程顺序调用问题咨询
你当前的代码会为每个任务创建独立线程且同时调用start(),所以所有任务会并行执行;直接调用join()会阻塞主线程(Kivy GUI运行在主线程),因此会导致界面卡死。
最优实现方案:单工作线程串行执行任务
你不需要为每个任务单独创建线程,仅需要启动1个后台工作线程,在线程内部按顺序执行所有选中的任务即可,既保证执行顺序,又不会占用主线程资源导致界面卡顿。
注意事项
Kivy的所有GUI控件属性修改必须在主线程执行,因此工作线程中更新进度条的操作需要通过kivy.clock.Clock.schedule_once调度到主线程执行,否则会出现更新异常或者程序崩溃。
完整修改代码
首先导入依赖:
from threading import Thread from kivy.clock import Clock
修改按钮触发的逻辑:
scripts_to_run = ListProperty([]) # 进度更新方法,仅在主线程被调度执行 def update_progress(self, value): self.progress_bar.value = value def process_data(self): # 按选择顺序整理待执行任务队列 task_queue = [] if "move_data" in self.scripts_to_run: # 若move_data是耗时操作,也可放入task_queue中执行 self.move_data() task_queue.append(self.produce_data_file) if "histograms" in self.scripts_to_run: task_queue.append(self.histograms) if "log_histograms" in self.scripts_to_run: task_queue.append(self.log_histograms) # 后台工作线程逻辑:串行执行所有任务 def task_worker(): for task in task_queue: # 执行当前任务前重置进度条为0 Clock.schedule_once(lambda dt: self.update_progress(0), 0) # 执行当前任务,任务内部上报进度时需通过Clock.schedule_once调用update_progress task() # 当前任务执行完成后进度拉满,可根据需求调整停留逻辑 Clock.schedule_once(lambda dt: self.update_progress(100), 0) # 启动单个后台工作线程,daemon=True保证程序退出时线程自动销毁 Thread(target=task_worker, daemon=True).start()
任务函数适配示例
以produce_data_file为例,内部更新进度的写法需要调整为:
def produce_data_file(self): # 假设任务共分4步 total_step = 4 for step in range(total_step): # 执行对应步骤的业务逻辑 # ... # 计算进度并调度到主线程更新UI progress = (step + 1) * 100 / total_step Clock.schedule_once(lambda dt, val=progress: self.update_progress(val), 0)
内容的提问来源于stack exchange,提问作者Jack Foster
相关产品推荐
相关产品推荐

