I am using a thread which calls two functions and the entire process takes ~15 seconds to complete.
How can I stop this thread using a Button widget if I want to interrupt the process before it completes?
In general, itâs not possible/desirable to forcibly stop a thread, so the best you could do is have the thread periodically check whether it should finish. A good way of doing that is with an Event
object from the threading
module.
If possible can you show with example?
Setting âdaemon = Trueâ for the thread turned out to be the solution.
Since the 2 functions called were not in loop and I have used the Button to exit the program so setting my thread as âdaemonâ was helpful.
Setting daemon=True
marks the thread as to not block the interpreter
from shutting down. Handy for some worker threads, but not always the
right thing to do.
For example, if the worker thread is processing some queue of requests,
you would want it to run to completion instead of terminating early, and
in this case you would thus want some notion of âclosingâ the queue so
that the worker could see that there are no more requests coming.
It also isnât what you asked for You asked for a way to shut down a
thread, and as Matthew pointed out that is usually signaled by setting a
flag of some kind, which the thread should poll on a regular basis.
Cheers,
Cameron Simpson cs@cskk.id.au
Can you show an example to end the thread ?
I can then use a new button which only closes the queue used by this thread but does not quit the program.
If you use a global variable (ugh!) you can do it like this:
# the global variable
stop_flag = False
def worker(....):
global stop_flag
while not stop_flag:
... do a unit of work ...
This function which would run in your thread runs until stop_flag is
true, checking it once per unit of work, whatever that is. Then your
cancel buttonâs callback function can look like this:
def cancel_button_callback(...):
global stop_flag
stop_flag = True
Using a global isnât very general. Usually I pass in something to check,
for example some kind of object with a .cancelled
attribute. Then your
worker function might look like this:
def worker(runstate, ....):
while not runstate.cancelled:
... do a unit of work ...
Then when you dispatch the worker you supply this object as a parameter:
from types import SimpleNamespace
runstate = SimpleNamespace(cancelled=False)
T = Thread(target=worker, args=(runstate, ....))
T.start()
Provided you keep the runstate
object around, you can then cancel the
worker like this:
runstate.cancelled = True
Cheers,
Cameron Simpson cs@cskk.id.au