如何解决 Tkinter 中的多处理问题?

How to solve Problem with Multiprocessing in Tkinter?

在这里,我在 tkinter 中使用多重处理 运行 多种算法。起初我尝试使用线程,但它不能在我的程序中正常工作。下面是我的程序工作流程的一个想法,它的工作原理是这样的,但只是功能不同:

from tkinter import *
from multiprocessing import Process

def SquarFunc(Square):
    for i in range(1,1000):
        Square.set(str(i**2))

def CubeFunc(Cube):
    for i in range(1,1000):
        Cube.set(str(i**3))

if __name__ == "__main__":
    window= Tk()
    Square= StringVar()
    Cube= StringVar()
    window.geometry("500x500")
    A= Label(window, textvariable= Square)
    A.place(x=200, y=200)
    B= Label(window, textvariable= Cube)
    B.place(x=300, y=300)

    Squaring= Process(target=SquarFunc, args=(Square, ))
    Cubing= Process(target=CubeFunc, args=(Cube, ))
    Squaring.start()#Error originates here
    Cubing.start()
    Squaring.join()
    Cubing.join()
    window.mainloop()

产生的错误是这样的:

TypeError: cannot pickle '_tkinter.tkapp' object

有人知道如何解决这个问题吗??提前致谢!

这里是一个使用 multiprocessing 时如何与其他进程通信的示例(解释在注释中,time.sleep 仅用于示例,否则这些循环将在几微秒内完成):

from tkinter import Tk, StringVar, Label
from multiprocessing import Process, Manager
import time


def square_func(d, name):
    for i in range(1, 1000):
        # update data in the shared dict
        d[name] = i
        time.sleep(0.1)


def cube_func(d, name):
    for i in range(1, 1000):
        # update data in the shared dict
        d[name] = i
        time.sleep(0.1)


def update_string_vars(d, *variables):
    for var in variables:
        # get the value from shared dict
        value = d[str(var)]
        if value is not None:
            # set string var to the value
            var.set(str(value))
    # schedule this to run again
    window.after(100, update_string_vars, d, *variables)


# cleanup process upon closing the window in case 
# processes haven't finished
def terminate_processes(*processes):
    for p in processes:
        p.terminate()


if __name__ == "__main__":
    window = Tk()
    window.geometry("500x500")
    # bind the terminator to closing the window
    window.bind('<Destroy>', lambda _: terminate_processes(
            square_process, cube_process))

    square_var = StringVar()
    cube_var = StringVar()

    Label(window, text='Square:').pack()
    Label(window, textvariable=square_var).pack()

    Label(window, text='Cube:').pack()
    Label(window, textvariable=cube_var).pack()
    
    # create the manager to have a shared memory space
    manager = Manager()
    # shared dict with preset values as to not raise a KeyError
    process_dict = manager.dict({str(square_var): None, str(cube_var): None})

    square_process = Process(
        target=square_func, args=(process_dict, str(square_var))
    )
    cube_process = Process(
        target=cube_func, args=(process_dict, str(cube_var))
    )
    square_process.start()
    cube_process.start()
    
    # start the updater
    update_string_vars(process_dict, square_var, cube_var)

    window.mainloop()

有用:

另请参阅:
我强烈建议在导入内容时不要使用通配符 (*),您应该导入您需要的内容,例如from module import Class1, func_1, var_2 等等或导入整个模块:import module 然后你也可以使用别名:import module as md 或类似的东西,关键是不要导入所有东西,除非你真的知道你在做什么;名称冲突是问题所在。

我强烈建议关注 PEP 8 - Style Guide for Python Code。函数和变量名称应在 snake_case 中,class 中的名称应在 CapitalCase 中。如果用作关键字参数 (func(arg='value')) 的一部分,则在 = 周围不要有 space,但如果用于 =,则在 space 周围赋值 (variable = 'some value')。在运算符周围有 space(+-/ 等:value = x + y(此处除外 value += x + y))。在函数和 class 声明周围有两个空行。对象方法定义周围有一个空行。