Starting n threads with same function at different times.

huangapple go评论68阅读模式
英文:

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)

huangapple
  • 本文由 发表于 2023年2月13日 22:42:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75437358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定