如何在python中停止/暂停工作线程,在主线程中执行操作并将结果发送到工作线程



我有一个脚本,它使用用户输入,并在此基础上生成一些数据(下面的代码(。脚本使用线程,因此在后台任务运行时GUI不会冻结。

我的问题是,是否可以暂停工作线程,向用户请求一些输入,将其发送到工作线程,然后继续操作?

from tkinter.constants import LEFT, RIGHT, S
import tkinter.messagebox
import tkinter as tk, time, threading, random, queue
from tkinter import NORMAL, DISABLED, filedialog
class GuiPart(object):
def __init__(self, master, client_instance):
canvas = tk.Canvas(master, height=600, width=1020, bg="#263D42")
canvas.pack()
self.button1 =  tk.Button(master, text="Mueller Matrix - MMP mode", padx=10, 
pady=5, bd = 10, font=12, command=client_instance.start_thread1)
self.button1.pack(side = LEFT)

def files(self):
self.filena = filedialog.askopenfilenames(initialdir="/", title="Select File",
filetypes = (("comma separated file","*.csv"), ("all files", "*.*")))
return self.filena
def processing_done(self):
tkinter.messagebox.showinfo('Processing Done', 'Process Successfully Completed!')
return

class ThreadedClient(object):
def __init__(self, master):

self.running=True
self.gui = GuiPart(master, self)
def start_thread1(self):
thread1=threading.Thread(target=self.worker_thread1)
thread1.start()
def worker_thread1(self):
if self.running:
self.gui.button1.config(state=DISABLED) # can I disable the button from the main thread?
user_input = self.gui.files() # can I pause the Worker thread here so ask the user_input from main loop?
time.sleep(5) # to simulate a long-running process
self.gui.processing_done()
self.gui.button1.config(state=NORMAL)
root = tk.Tk()
root.title('test_GUI')
client = ThreadedClient(root)
root.mainloop()

我问这个问题是因为我的脚本不时地突然结束,说GUI不是主循环的一部分。谢谢你的帮助!

通常,您应该从主线程运行GUI。

tkinter是否是线程安全的存在一些混淆。也就是说,如果可以从除主线程之外的任何线程调用tkinter函数和方法。Python3的文档显示"是"。tkinter的C源代码中的注释表示"它很复杂",这取决于tcl的构建方式。

如果您的tkinter是使用线程支持构建的,那么您应该能够从Python 3中的其他线程调用tkinter函数和方法。AFAIK,从python.org下载的tkinter已经启用了线程。

如果您希望能够暂停其他线程,则应该创建一个全局变量,例如pause = False。额外的线程应该定期读取这个值,并在设置为true时暂停计算,例如:

def thread():
while run:
while pause:
time.sleep(0.2)
# do stuff

同时,运行在主线程中的GUI应该是唯一一个写入pause值的GUI,例如在小部件回调中。

一些示例回调:

def start_cb():
pause = False  # So it doesn't pause straight away.
run = True
def stop_cb():
pause = False
run = False
def pause_cb():
pause = True
def continue_cb():
pause = False

如果您有更复杂的全局数据结构,可以通过几个线程进行修改,那么您绝对应该保护对那些具有Lock的全局数据的访问。

第1版

无类的线程tkinter程序:

  • 简单的线程tkinter示例程序
  • 解锁ms-excel文件的真实世界示例

第2版:

来自_tkinter:的python源代码

如果Tcl是线程化的,这种方法将不再有效。Tcl解释器仅在创建它的线程中有效,并且所有Tk活动也必须发生在这个线程中。这意味着必须在创建口译译员可以从其他线程调用命令;_tkinter将为解释器线程排队一个事件然后执行命令并将结果传回。如果主线程不在主循环中,调用命令会导致例外如果主循环正在运行但不处理事件,命令调用将被阻止。

您可以在此处阅读全部评论。

最新更新