这是我的代码:
# -*- coding:utf-8 -*-
import time
import tkinter as tk
from multiprocessing import Pool
class Application(tk.Tk):
def __init__(self):
super(self.__class__, self).__init__()
self.title('test')
self.geometry('300x500')
self.main_ui()
self.pool = Pool(10)
def a(self, word):
print(word, ' start')
time.sleep(5)
print(word, 'end')
def call_a(self, word):
self.pool.apply_async(self.a, (word,))
def main_ui(self):
bnt1 = tk.Button(self, text='a', command=lambda: self.call_a('a'))
bnt1.place(x=0, y=0, height=100, width=70)
bnt1 = tk.Button(self, text='b', command=lambda: self.call_a('b'))
bnt1.place(x=0, y=100, height=100, width=70)
# pass
def main():
app = Application()
app.mainloop()
if __name__ == '__main__':
main()
我想让print(word, ' start')
和print(word, ' start')
在其他处理中没有tkinter的阻塞过程,因为time.sleep(5)
有tkinter阻塞过程。正如我认为的那样,两个过程都赢了;不够,所以我使用了一个处理池。但这次程序不起作用(当我按下按钮时,def a(self,word)
不起作用(。
gui可以正确显示,但当我按下按钮时,def a(self, word):
不工作,我不知道为什么以及如何解决这个问题。
顺便说一下,我用的是蟒蛇3。
谢谢
不能忽略multiprocessing.Pool.apply_async
的返回值。它不是设计为即发即弃机制运行";背景";任务。如果您修改代码以检查结果:
def call_a(self, word):
res = self.pool.apply_async(self.a, (word,))
ret = res.get()
print("return value:", ret)
当你点击a
按钮时,你会看到:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python3.10/tkinter/__init__.py", line 1921, in __call__
return self.func(*args)
File "/home/lars/tmp/python/gui.py", line 25, in <lambda>
bnt1 = tk.Button(self, text="a", command=lambda: self.call_a("a"))
.
.
.
TypeError: cannot pickle '_tkinter.tkapp' object
因此,问题是您对apply_async
的调用失败,出现了异常,但您从未检索到它。失败的原因是apply_async
试图pickle对象以便将它们发送给工作者,但这在Tk应用程序对象中是不可能的。
要使代码正常工作,可能需要一些重新架构:例如,与其尝试使用multiprocessing.Pool
,不如考虑手动生成多个进程(或线程!(,然后使用队列将数据传递给工作线程。