Elperdano
Elperdano

Reputation: 29

Starting n threads with same function at diffrent times

I'm currently working with Tkinter to create a GUI for my Script. Among other things there is a function which writes and save some Data in some Files. To visualize the progress for the User i got an label which shows the progress. When i press the button to execute the function

button_download_data = tk.Button(text="Get Data",command=gatherData)

the window freezes and beside the counter for the progress increasaes it isnt shown due to the window is frozen. My solution was to start the function in a new thread using the threading modul.

button_download_data = tk.Button(text="Get Data",command=threading.Thread(target=gatherData).start)

Now the progress is showed but i cant press the button again because i get an error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\WPy64-31050\python-3.10.5.amd64\lib\tkinter\__init__.py", line 1921, in __call__
    return self.func(*args)
  File "C:\WPy64-31050\python-3.10.5.amd64\lib\threading.py", line 930, in start
    raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once

I tried to "kill" the thread when the function is done with raise Exception() and sys.Exit() but it doesn't work at all. I figuerd out that i can outsource the thread start out of the tkinter button line with:

def gatherDate():
    do something

def threadStart():
    threading.Thread(target=gatherData).start

button_download_data = tk.Button(text="Get Data",command=threadStart)

and i think it might help to start a new thread on button press and not the same again but i cant imagine how.

Upvotes: 1

Views: 55

Answers (1)

JRiggles
JRiggles

Reputation: 6820

You should be able to handle this by creating a separate function to spawn new worker threads as needed - here's a very basic example

import tkinter as tk
from threading import Thread
from time import sleep  # for example - simulate a long-running process


def get_data():
    print('foo')  # do whatever you need to do here
    sleep(2.0)  # simulate the thread 'working' on something...for example


def spawn_thread():
    t = Thread(target=get_data, daemon=True)
    t.start()


root = tk.Tk()
button_download_data = tk.Button(root, text='Get Data', command=spawn_thread)
button_download_data.pack()


if __name__ == '__main__':
    root.mainloop()

You could simplify spawn_thread a little by skipping the variable assignment t=... and doing Thread(target=get_data, daemon=True).start() instead (as long as you don't need access to the Thread object t for anything else)

Upvotes: 2

Related Questions