Need help to stop a thread using Button in 'tkinter'?

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.

1 Like

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 :slight_smile: 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

1 Like

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

1 Like