python3 Tkinter实现线程控制程序暂停、恢复和终止 您所在的位置:网站首页 python如何关闭子线程 python3 Tkinter实现线程控制程序暂停、恢复和终止

python3 Tkinter实现线程控制程序暂停、恢复和终止

2024-03-17 06:04| 来源: 网络整理| 查看: 265

Python3 tkinter中使用event.wait()让多线程暂停、恢复和终止

最近使用tkinter完成一个小工具,期间在百度搜索到很多用多线程event.wait()使程序暂停的demo,控制while死循环的暂停。这里分享一个实例,使用event.wait()实现 在tkinter中用按钮让一个耗时程序暂停、恢复和终止。

实现步骤: 1.导入相关库

import threading import time from mttkinter import mtTkinter as tk import tkinter.messagebox # 引入弹窗库,防止解释器弹出报错。

这里使用mttkinter代替,因为在tkinter中使用多线程会报错:

main thread is not in main loop

这是tkinter的问题,使用mttkinter代替就好

2.创建线程类

class MyThread(threading.Thread): def __init__(self, func, *args): # 线程初始化 super().__init__(target=func, args=args) self.func = func self.args = args self.__flag = threading.Event() # 用于暂停线程的标识 self.__flag.set() # 设置为True self.__running = threading.Event() # 用于停止线程的标识 self.__running.set() # 将running设置为True # 开始执行 self.thread_run() # 打包进线程(耗时的操作)防止tkinter单线程阻塞 def thread_run(self): self.__flag.wait() # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回 self.setDaemon(True) # 守护--就算主界面关闭,线程也会留守后台运行 self.start() # 在这里开始 def pause(self): self.__flag.clear() # 设置为False,让线程阻塞 print('阻塞线程') def resume(self): self.__flag.set() # 设置为True,让线程停止阻塞 print('已恢复线程') def stop(self): self.__flag.set() # 将线程从暂停状态恢复, 如何已经暂停的话 self.__running.clear() # 设置为False

这里定义了线程类,原理很简单,传入一个函数,使用Threading为函数创建线程,然后定义暂停,恢复,终止的函数,通过threading.Event()来实现

3.tkinter窗口和业务函数

class TkinterWindow: def __init__(self): self.isRun = False # 是否有线程正在执行 self.myThread = None # 正在执行的线程(MyThread类的对象) # 信息窗口 def messagebox(self): def main_active(pay_type, act_type): try: ... # 这里的函数需要请求多个接口,返回数据需要一定的时间 self.user_login() # 在每个耗时操作的函数后加上如下代码 self.myThread._MyThread__flag.wait() # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回 self.zf_adjust_search(paytype=1) self.myThread._MyThread__flag.wait() # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回 self.zjzfAdjust() # 耗时函数 except AttributeError: print("任务已终止") # 捕获异常,当点击终止任务时,清空self.myThread,这时可以用作跳出循环 # 判断是否已被中断(正常结束就关闭线程) if self.myThread: self.myThread.stop() self.myThread = None # 执行结束后,关闭线程 self.isRun = False self.ternimal_print('任务已结束', 'info') def thread_it(func, *args): # 开始线程 if self.myThread: tkinter.messagebox.showinfo(title='提示', message='当前已存在执行的任务,请结束任务后再试') else: self.myThread = MyThread(func, *args) # 用传入的业务函数实例化一个线程 # 暂停或恢复 def pause_resume(): if self.myThread: # 如果存在执行的任务 # 暂停和恢复 if self.isRun: # True表示正在运行 if self.myThread._MyThread__flag.is_set(): # 如果为True表示在执行(返回False表示暂停) mess = tkinter.messagebox.askquestion(title='提示', message='确认要暂停任务?') if mess == 'no': print('Choose no!') else: print('choose yes') self.myThread.pause() self.isRun = False self.ternimal_print('暂停程序', 'warning') # 在label显示任务已暂停 var1.set("任务已暂停") else: tkinter.messagebox.showinfo(title='提示', message='没有需要暂停的任务') else: self.myThread.resume() self.isRun = True # 在label显示任务恢复,并显示正在执行的任务 var1.set("恢复任务程序运行") self.ternimal_print('恢复程序运行', 'warning') else: tkinter.messagebox.showinfo(title='提示', message='当前没有正在执行的任务') # 终止函数 def stop(): if self.myThread: # 如果存在执行的任务 mess = tkinter.messagebox.askquestion(title='提示', message='确认结束任务?') if mess == 'no': print('Choose no!') else: print('choose yes') self.myThread.stop() # 结束任务 self.isRun = False self.myThread = None self.ternimal_print('已结束任务', 'warning') # 在label中显示已结束任务 var1.set("任务已终止") else: tkinter.messagebox.showinfo(title='提示', message='当前没有正在执行的任务') window = tk.Tk() # 生成主窗口,命名 window window.title('信息查看窗口') # 定义主窗口标题 window.geometry('800x600') # 定义主窗口的长宽 fm_btn = tk.Frame(window) # 按钮 fm_btn.pack() # 结束按钮 tk.Button(fm_btn, text='结束任务', command=stop).pack(side='right', fill='y', expand='yes') # 暂停/恢复按钮 tk.Button(fm_btn, text='暂停/恢复', command=pause_resume).pack(side='right', fill='y', expand='yes') # 按钮选择一项更正 耗时操作,使用线程 tk.Button(fm_btn, text='更正当前选项', command=lambda: thread_it(main_active, 'zjzf', 'get')).pack(side='right', fill='y', expand='yes') # 定义一个按钮,用来后续触发弹窗 # 按钮遍历更正全部 tk.Button(fm_btn, text='更正所有项', command=lambda: thread_it(main_active, 'zjzf', 'loop')).pack(side='right', fill='y', expand='yes') # 按钮选择一项更正 tk.Button(fm_btn, text='更正当前选项SQ', command=lambda: thread_it(main_active, 'sqzf', 'get')).pack(side='right', fill='y', expand='yes') # 定义一个按钮,用来后续触发弹窗 # 按钮遍历更正全部 tk.Button(fm_btn, text='更正所有项SQ', command=lambda: thread_it(main_active, 'sqzf', 'loop')).pack(side='right', fill='y', expand='yes') # 三个耗时函数 def user_login(self): ... def zf_adjust_search(self, paytype): ... def zjzfAdjust(self) # 耗时函数 ...

按钮绑定创建线程函数,业务函数作为该函数的参数,实例化一个线程 然后通过pause_resume和stop函数来控制线程的暂停和恢复



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有