如何创建一个不确定的进程,在后台启动一个线程,并在python中线程完成后再次执行一些操作
我正在尝试在Python3的新顶层窗口中为某个进程创建一个不确定的进度条,然后为该进程启动线程。我想要的是,进度条启动,线程也在后台启动,一旦线程完成执行,就会显示一些消息,表明任务已完成 代码:如何创建一个不确定的进程,在后台启动一个线程,并在python中线程完成后再次执行一些操作,python,multithreading,tkinter,Python,Multithreading,Tkinter,我正在尝试在Python3的新顶层窗口中为某个进程创建一个不确定的进度条,然后为该进程启动线程。我想要的是,进度条启动,线程也在后台启动,一旦线程完成执行,就会显示一些消息,表明任务已完成 代码: class myThread(threading.Thread): def __init__(self, threadID): threading.Thread.__init__(self) self.threadID = threadID def
class myThread(threading.Thread):
def __init__(self, threadID):
threading.Thread.__init__(self)
self.threadID = threadID
def run(self):
print("Starting the thread")
func()
print("Ending the thread")
def func():
some task
...
new_top = Toplevel()
new_top.title("New Top Level")
new_top.geometry("400x170")
label = Label(new_top, text='Doing some work', justify=CENTER, bg="#CBFDCB").place(x=43,y=30)
progress_bar = ttk.Progressbar(new_top, orient="horizontal", mode="indeterminate", takefocus=True, length=320)
progress_bar.place(x=40, y=80)
progress_bar.start()
thread1 = myThread(1)
thread1.start()
thread1.join()
...
执行线程后操作
我的问题是,如果调用thread1.join(),则带有标签和进度条的顶级窗口永远不会出现,如果我跳过这一部分,则线程执行后的操作不会运行。TKinter通过使用无限主循环来等待和处理事件-截取按压、重绘元素等。(查看更多信息) 当您调用
join()
时,您强制主线程(tkinter在其中运行)等待新启动的线程完成执行后再继续,因此无法使用进度条绘制顶级窗口。因此,这实际上不是一个选项
另一方面,您需要知道您的子线程何时完成执行。您可以使用
mythread.isAlive()检查线程是否仍然处于活动状态
,但不能在循环中执行,因为它会再次停止tkinter的主循环的执行,从而绘制接口。我建议寻找解决此问题的方法。tkinter的工作原理是使用无限主循环来等待和处理事件-截取按下、重新绘制元素等(查看更多信息)
当您调用join()
时,您强制主线程(tkinter在其中运行)等待新启动的线程完成执行后再继续,因此无法使用进度条绘制顶级窗口。因此,这实际上不是一个选项
另一方面,您需要知道您的子线程何时完成执行。您可以使用
mythread.isAlive()检查线程是否仍然处于活动状态
,但不能在循环中执行,因为它会再次停止tkinter的主循环的执行,从而绘制接口。我建议您考虑处理此问题。使用tkinter执行线程可能会有点棘手。以下是一些您想要的代码。我的第一个版本无法正常工作,因为我尝试了o从线程的.run
方法内部销毁Tkinter窗口。这不起作用:窗口关闭,但.run
方法在root.destroy
调用后没有进展。因此,现在我们有了一个函数,它每100毫秒检查一次线程是否仍处于活动状态,如果它不处于活动状态,我们将关闭Tkinter窗户
import threading
import tkinter as tk
from tkinter import ttk
from time import sleep
class myThread(threading.Thread):
def __init__(self, threadID):
threading.Thread.__init__(self)
self.threadID = threadID
def run(self):
print("Starting the thread")
func()
print("Ending the thread")
def func():
for i in range(10):
print(i)
sleep(1)
def check_thread(th):
if not th.isAlive():
root.destroy()
root.after(100, check_thread, th)
root = tk.Tk()
root.title("New Top Level")
root.geometry("400x170")
tk.Label(root, text='Doing some work', justify=tk.CENTER, bg="#CBFDCB").place(x=43, y=30)
progress_bar = ttk.Progressbar(root, orient="horizontal",
mode="indeterminate", takefocus=True, length=320)
progress_bar.place(x=40, y=80)
progress_bar.start()
thread1 = myThread(1)
thread1.start()
root.after(100, check_thread, thread1)
root.mainloop()
print("Doing post-thread stuff")
使用Tkinter执行线程处理可能有点棘手。以下是一些您想要的代码。我的第一个版本无法正常工作,因为我试图从线程的
.run
方法内部破坏Tkinter窗口。这不起作用:窗口关闭,但根目录后,run
方法没有进展。销毁
调用。因此,现在我们有了一个函数,它每100毫秒检查一次线程是否仍处于活动状态,如果线程不处于活动状态,则关闭Tkinter窗口
import threading
import tkinter as tk
from tkinter import ttk
from time import sleep
class myThread(threading.Thread):
def __init__(self, threadID):
threading.Thread.__init__(self)
self.threadID = threadID
def run(self):
print("Starting the thread")
func()
print("Ending the thread")
def func():
for i in range(10):
print(i)
sleep(1)
def check_thread(th):
if not th.isAlive():
root.destroy()
root.after(100, check_thread, th)
root = tk.Tk()
root.title("New Top Level")
root.geometry("400x170")
tk.Label(root, text='Doing some work', justify=tk.CENTER, bg="#CBFDCB").place(x=43, y=30)
progress_bar = ttk.Progressbar(root, orient="horizontal",
mode="indeterminate", takefocus=True, length=320)
progress_bar.place(x=40, y=80)
progress_bar.start()
thread1 = myThread(1)
thread1.start()
root.after(100, check_thread, thread1)
root.mainloop()
print("Doing post-thread stuff")