Everywhere I look when researching tkinter multithreading, the things I find mention tkinter must run on the main thread (like lots of GUI frameworks), and when a separate thread needs to communicate with the GUI, one must use queues instead of accessing the widgets directly from the worker thread.
I was trying to learn to use the queue method, but of course initially I wanted to see what happens if I do it wrong, so I wrote this piece of code, which approximates Pi (π) for a few seconds:
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()
As far as I understand, lines marked by the ???
comment are the problem. But this code runs just fine. Stays responsive, both the label and the progress bar are updated.
Is this cross-thread error undeterministic in terms of sometimes it happens / sometimes not? Would this code potentially break eventually? Or am I naive to believe the only good solution is a queue? I believe in C# this would yield a cross-thread operation not valid
, but python doesn't seem to have a problem with it.