Why does the multithread function not run before the timer?

Viewed 38

I am trying to use multithreading to show a loading wheel while doing some background calculations. I try to start the multithreaded function, and then run a timer to simulate the calculations. The problem is the thread first starts running when the timer is over, even though I am starting the thread first...

from tkinter import *
from tkinter import messagebox
import time
from threading import *
from PIL import Image, ImageTk
# Create Object
root = Tk()
  
# Set geometry
root.geometry("400x400")
flag = True
# use threading
def threading():
    t1=Thread(target=work)
    t1.start()
    time.sleep(10)
# work function
def work():
    print("sleep time start")
    image = Image.open("Static/spinner0.png")
    img = ImageTk.PhotoImage(image)
    lab = Label(root,image=img)
    lab.pack()
    while flag:
        for i in range(8):
            image = Image.open("Static/spinner"+str(i)+".png")
            img = ImageTk.PhotoImage(image)
            lab['image'] = img
            time.sleep(0.2)
        #return False
    print("sleep time stop")

def on_closing():
    if messagebox.askokcancel("Quit", "Do you want to quit?"):
        flag = False
        root.destroy()
        
# Create Button
Button(root,text="Click Me",command = threading).pack()

# Execute Tkinter
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
1 Answers

Just putting the answer here to avoid people digging comments for the solution.

One way to do this is to have both the calculations and the updating function running on extra different threads, this way the main process event loop stays uninterrupted and you get to call time.sleep, which is fine so long as it doesn't happen in your main thread.

A thread in python consumes below 100KB of memory (plus memory for variables in code running on it), so it's fine to have multiple threads running.

from tkinter import *
from tkinter import messagebox
import time
from threading import *
from PIL import Image, ImageTk

# Create Object
root = Tk()

# Set geometry
root.geometry("400x400")
flag = True


# use threading
def threading():
    t1 = Thread(target=work)
    t1.start()
    t2 = Thread(target=time.sleep,args=(10,)) # the heavy computation function.
    t2.start()
    # control is given back to the main event loop

# work function
def work():
    print("sleep time start")
    image = Image.open("Static/spinner0.png")
    img = ImageTk.PhotoImage(image)
    lab = Label(root,image=img)
    lab.pack()
    while flag:
        for i in range(8):
            image = Image.open("Static/spinner"+str(i)+".png")
            img = ImageTk.PhotoImage(image)
            lab['image'] = img
            time.sleep(0.2)
        #return False
    print("sleep time stop")


def on_closing():
    if messagebox.askokcancel("Quit", "Do you want to quit?"):
        flag = False
        root.destroy()


# Create Button
Button(root, text="Click Me", command=threading).pack()

# Execute Tkinter
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()
Related