英文:
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 that writes and saves some data in some files. To visualize the progress for the user, I have a label that 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 besides the progress counter increasing, it isn't shown because the window is frozen. My solution was to start the function in a new thread using the threading module:
button_download_data = tk.Button(text="Get Data", command=threading.Thread(target=gatherData).start)
Now the progress is shown, but I can't 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 figured out that I can outsource the thread start out of the tkinter button line with:
def gatherData():
# 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 a button press and not the same again, but I can't imagine how.
英文:
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.
答案1
得分: 2
你可以通过创建一个单独的函数来根据需要生成新的工作线程来处理这个问题 - 这里有一个非常基本的示例
import tkinter as tk
from threading import Thread
from time import sleep # 举例 - 模拟一个长时间运行的过程
def get_data():
print('foo') # 在这里执行你需要的操作
sleep(2.0) # 模拟线程在执行某事...
def spawn_thread():
Thread(target=get_data, daemon=True).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()
你可以通过跳过变量分配t=...
并改为Thread(target=get_data, daemon=True).start()
来简化spawn_thread
函数(只要你不需要在其他地方访问Thread
对象t
)。
英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论