0

I am pretty new to Python and have a question about threading.

I have one function that is called pretty often. This function starts another function in a new Thread.

def calledOften(id):
    t = threading.Thread(target=doit, args=(id))
    t.start()    

def doit(arg):
    while true:
    #Long running function that is using arg

When calledOften is called everytime a new Thread is created. My goal is to always terminate the last running thread --> At all times there should be only one running doit() Function.

What I tried: How to stop a looping thread in Python?

def calledOften(id):
    t = threading.Thread(target=doit, args=(id,))
    t.start()
    time.sleep(5)
    t.do_run = False

This code (with a modified doit Function) worked for me to stop the thread after 5 seconds. but i can not call t.do_run = False before I start the new thread... Thats pretty obvious because it is not defined...

Does somebody know how to stop the last running thread and start a new one?

Thank you ;)

Cornelius
  • 306
  • 4
  • 14
  • Force-terminating threads is dangerous as heck. `threading` doesn't support it. The Java devs tried to support it, realized it was a terrible idea, and deprecated all the relevant methods. – user2357112 Mar 27 '20 at 08:48
  • You're not supposed to send the "don't run" signal to the new thread you're starting. You're supposed to send it to the *old* thread. You need to keep a reference to that thread. – user2357112 Mar 27 '20 at 08:50
  • Ah ok that would be a solution too. Can you provide with a small hint please? – Cornelius Mar 27 '20 at 08:51

1 Answers1

0

I think you can decide when to terminate the execution of a thread from inside the thread by yourself. That should not be creating any problems for you. You can think of a Threading manager approach - something like below

import threading


class DoIt(threading.Thread):
    def __init__(self, id, stop_flag):
        super().__init__()

        self.id = id
        self.stop_flag = stop_flag

    def run(self):
        while not self.stop_flag():
            pass  # do something


class CalledOftenManager:
    __stop_run = False
    __instance = None

    def _stop_flag(self):
        return CalledOftenManager.__stop_run

    def calledOften(self, id):
        if CalledOftenManager.__instance is not None:
            CalledOftenManager.__stop_run = True
            while CalledOftenManager.__instance.isAlive():
                pass  # wait for the thread to terminate

            CalledOftenManager.__stop_run = False
            CalledOftenManager.__instance = DoIt(id, CalledOftenManager._stop_flag)
            CalledOftenManager.__instance.start()


# Call Manager always
CalledOftenManager.calledOften(1)
CalledOftenManager.calledOften(2)
CalledOftenManager.calledOften(3)

Now, what I tried here is to make a controller for calling the thread DoIt. Its one approach to achieve what you need.

Kris
  • 8,680
  • 4
  • 39
  • 67
  • Wow thank you for your solution ;). Just one small question. There are two arguments that need to be passed to the calledOften function... What is the first one? – Cornelius Mar 27 '20 at 09:19
  • self is the instance representation of python. You can read about it. It will be automatically placed when you have an object to call the method – Kris Mar 27 '20 at 11:37