I have a Tkinter application, in which I have a button, calling a function. To avoid freezing the UI, while this function processes, I'm starting it within its own thread.
If I spawn the thread within the same class, as the method I'm calling is defined, my UI still freezes. The only way I have been able to fix this is by creating a Threader class, whose sole purpose, is to call a function within a new thread.
I have tried shaving down my app class, to only the relevant things, for this problem, but let me know if you are suspecting that I cut away too much:
from threader import Threader
from threading import Thread
from tkinter import ttk
import tkinter as tk
class App(tk.Tk):
def __init__(self):
...
self.run_btn=ttk.Button(self, text='Run', command=self.start_clicked, width=15)
self.Threader = Threader()
...
def start_clicked(self):
Thread(target=self.my_func()).start() # this freezes my ui
# self.Threader.run_thread(self.my_func()) # this does not freeze my ui
def my_func(self):
# some logic
This is my Threader class:
from threading import Thread
class Threader:
def run_thread(self, name, func):
Thread(target=func).start()
In my App class I have included both ways I have tried spawning the thread, within the start_clicked function. The first one is the one freezing my UI, and the one commented-out, in which I spawn the thread, through my Threader class, is the one which doesn't.
In my mind, there shouldn't be a difference, so I can't figure out why one works, and the other doesn't.
Consider this line of code:
Thread(target=self.my_func()).start()
Functionally, it is exactly the same as this:
result = self.my_func()
Thread(target=result).start()
See the problem? You are immediately calling self.my_func()
in the current thread.
The target
needs to be a reference to a function:
Thread(target=self.my_func)