Home > Net >  list and kill multiple threads using threading.enumerate()
list and kill multiple threads using threading.enumerate()

Time:12-08

I have some threads created with the class

import time, threading

class SetInterval:
    def __init__(self, interval, function):
        """SetInterval

        Args:
            interval (int number): seconds
            function (function): function to be executed after x seconds
        """
        self.interval = interval
        self.function = function
        self.stopEvent=threading.Event()
        thread=threading.Thread(target=self.__setInterval)
        thread.start()

    def __setInterval(self) :
        """while interval, execute passed func every time passed interval secs
        """
        nextTime = time.time()   self.interval
        while not self.stopEvent.wait(nextTime - time.time()) :
            nextTime  = self.interval
            try: self.function()
            except Exception as e: print(f'Exception [__setInterval]: ', e)
    
    def cancel(self):
        """sending class.cancel() stops the thread
        """ 
        print('[SetInterval][Cancel]: event canceled.')
        self.stopEvent.set()

any way to stop them all once i close my program with tkinter? because after it's compiled it keeps the threads open if you don't cancel everything before..

My tries...

def kill_all_threads():
    for thread in threading.enumerate():
        if not "MainThread" in thread.name:
            thread._Thread__stop()
# AttributeError: 'Thread' object has no attribute '_Thread__stop'
def kill_all_threads():
    for thread in threading.enumerate():
        if not "MainThread" in thread.name:
            thread.__stop()
# AttributeError: 'Thread' object has no attribute '__stop'
def kill_all_threads():
    for thread in threading.enumerate():
        if not "MainThread" in thread.name:
            thread.stopEvent.set()
# AttributeError: 'Thread' object has no attribute 'stopEvent'

In that way I call in main tkinter app

self.tkinter_thread = SetInterval(1, some_func)
#-----------------------------------------------------
self.low_health_interval = SetInterval(0.2, some_func)```, thats my 

def kill_all_threads():
    print('kill_all_threads')
    for t in threading.enumerate():
        if isinstance(t, SetInterval):
            print("Canceling", t)
            t.cancel()
            t.join()

CodePudding user response:

None of the methods you've tried exist on Thread objects, and SetInterval isn't a Thread either.

You'll have a better time if you derive directly from threading.Thread, because then you can use isinstance with threading.enumerate():

import time, threading


class IntervalThread(threading.Thread):
    def __init__(self, interval, function):
        threading.Thread.__init__(self)
        self.interval = interval
        self.function = function
        self._stop_event = threading.Event()

    def run(self):
        next_time = time.time()   self.interval
        while not self._stop_event.wait(next_time - time.time()):
            next_time  = self.interval
            try:
                self.function()
            except Exception as e:
                print(f"Exception [__setInterval]: ", e)

    def cancel(self):
        self._stop_event.set()


def main():
    IntervalThread(1, lambda: print("hello")).start()
    IntervalThread(2, lambda: print("world")).start()
    time.sleep(5)
    for t in threading.enumerate():
        if isinstance(t, IntervalThread):
            print("Canceling", t)
            t.cancel()
            t.join()


if __name__ == "__main__":
    main()

This prints out (e.g.)

hello
hello
world
hello
hello
world
hello
Canceling <IntervalThread(Thread-1, started 123145357873152)>
Canceling <IntervalThread(Thread-2, started 123145374662656)>

CodePudding user response:

You can always set the threads to be daemon threads which will automatically shutdown when the parent thread exits.

thread=threading.Thread(target=self.__setInterval, daemon=True)
  • Related