Python 为什么从工作线程更新tkinter小部件似乎有效?
在研究tkinter多线程时,我发现tkinter必须在主线程上运行(就像许多GUI框架一样),当一个单独的线程需要与GUI通信时,必须使用队列,而不是直接从工作线程访问小部件 我试图学习使用queue方法,但当然,一开始我想看看如果我做错了会发生什么,所以我写了这段代码,它在几秒钟内近似于Pi(π):Python 为什么从工作线程更新tkinter小部件似乎有效?,python,multithreading,tkinter,Python,Multithreading,Tkinter,在研究tkinter多线程时,我发现tkinter必须在主线程上运行(就像许多GUI框架一样),当一个单独的线程需要与GUI通信时,必须使用队列,而不是直接从工作线程访问小部件 我试图学习使用queue方法,但当然,一开始我想看看如果我做错了会发生什么,所以我写了这段代码,它在几秒钟内近似于Pi(π): import tkinter as tk from tkinter import ttk from threading import Thread import math window = t
import tkinter as tk
from tkinter import ttk
from threading import Thread
import math
window = tk.Tk()
window.geometry("300x150")
lbl = tk.Label(window, text="Press Start")
lbl.place(width=280, height=60, x=10, y=10)
pb = ttk.Progressbar(window)
pb.place(width=280, height=25, x=10, y=80)
def calculate():
""" 1 / i^2 = PI^2 / 6 """
s = 0.0
for i in range(1, 10000001):
s += (1 / i**2)
if i % 1000000 == 0:
value = math.sqrt(s * 6)
lbl.config(text=value) #???
pb.step(10) #???
def start():
lbl.config(text="Press Start")
#calculate() #irresponsive GUI this way, obviously
t = Thread(target=calculate)
t.start()
btn = tk.Button(window, text="Start", command=start)
btn.place(width=280, height=25, x=10, y=115)
window.mainloop()
据我所知,问题出在标有?
注释的行上。但是这段代码运行得很好。保持响应,标签和进度条都会更新
就有时发生/有时不发生而言,这个跨线程错误是不确定的吗?这段代码最终会被破解吗?还是我天真地认为唯一好的解决办法就是排队?我相信C#会产生一个无效的
跨线程操作
,但python似乎没有问题 在常规的消费者应用程序中,有一件事是不可接受的:当你点击“开始”按钮,然后在进度条结束前关闭窗口时会发生什么?在具有相互依赖部分的大型应用程序中,销毁另一个线程中使用的gui元素可能会产生不愉快的后果。我发现,当在终端中运行时,这个程序有时会在意外的出口处挂起,以至于ctrl-c无效
顺便说一句
s += (1 / i ** 2)
行正在进行整数除法,因此
s
的值只更改一次 在这段代码中,它太简单了,没有问题。当您有许多线程试图同时更新同一个小部件时,就会出现问题。@dilbert我理解,谢谢。可能是我编写的类似代码的重复,该代码在Mac(python 3.6)上运行良好,但在Linux(python 3.5)上崩溃。错误是“堆栈空间不足(无限循环?)”谢谢。是的,它真的应该是/
。我明白你关窗的意思,但排队也不能解决这个问题,不是吗?所以这是另一个问题。