Tkinter 中的多处理

Multiprocessing in Tkinter

我有以下代码,我在其中调用从小部件输入的按钮的函数。这是一个 运行 大约需要 4 分钟的函数,为了解决 tkinter window 的 'not responding' 问题,我想在不同的核心上获得 func 进程 运行ning 和终止,因为它可以通过应用程序 运行ning 在 mainloop 上使用不同的参数再次调用。我阅读了 multiprocessing 的文档, Pool 似乎是这里的选择,但我不知道如何在这里构建它。尝试了一些错误。

class database(tk.Tk):
    def __init__(self, *args, *kwargs):
        tk.Tk.__init__(self, *args, **kwargs):
        container= tk.Frame(self, width=1000, height=1000)
        container.pack(side="top", fill="both", expand= True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in ( msPage):      #many more pages here
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(msPage)

    def show_frame(self,cont):
        frame = self,frames[cont]
        frame.tkraise()

def MarkS(msVar):
    ms.func(msVar.get())       # func takes about 4 mins

class msPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        msVar = StringVar()
        msCal = Calendar(self, selectmode='day'
textvariable=msVar).pack(fill="both", expand=True)
        # button2 calls MarkS
        button2 = ttk.Button(self,
                             text="Get Data",
                             command=lambda: MarkS(msVar)).pack(pady=30, padx=10)                


app = database()
app.geometry("1066x568")
app.minsize(width=670, height=550)
app.mainloop()

这是一个独立示例,可以帮助您入门:

from multiprocessing import Process

class ms_var_class():
    value = None
    def __init__(self, value):
        self.value = value
    def get(self):
        return self.value

# This is to simulate type(ms)
class ms_class():
    process = None
    # This is for simulating your long running function
    def func(self, ms_var):
        print(ms_var)

def MarkS(msVar):
    ms.process = Process(target=ms.func, args=(msVar.get(),))
    ms.process.start()
    # Call ms.process.join() later

ms_var = ms_var_class("bogus")
ms = ms_class()
MarkS(ms_var)
if ms.process is not None:
    ms.process.join()

感谢 Mike 的评论并帮助我找到解决方案

这是我的做法

创建全局队列

q= queue.Queue()

在 class msPage

中定义了函数 MarkS
def MarkS(msVar):
        q.put([7 , datetime.datetime.strptime(msVar.get(), '%x').strftime('%d-%b-%Y').upper(),0])
        ThreadedTask(q).start()

7 是我为每个页面设置的 9 个函数的唯一编号 (class) 制作了另一个 class 的 ThreadedTask,如下面的 link Tkinter: How to use threads to preventing main event loop from "freezing"

class ThreadedTask(threading.Thread):
    def __init__(self,queue):
        threading.Thread.__init__(self)
        q = queue
    def run(self):
        items = q.get()
        if items[0]==7:
            ms.func(items[1])

ThreadedTask(q).start() 创建一个构造函数对象,运行 函数根据此处的参数自动启动,这当然是 q 的第一个元素,在我的例子中是 3 的列表.它被检测到并且所需的功能是另一个线程中的 运行 以防止 tkinter window 关闭。

希望对您有所帮助! :)