Запустить только один экземпляр потока - PullRequest
0 голосов
/ 27 марта 2020

Я довольно новичок в Python и у меня есть вопрос о многопоточности.

У меня есть одна функция, которая вызывается довольно часто. Эта функция запускает другую функцию в новом потоке.

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

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

При вызове callOften каждый раз, когда создается новый поток. Моя цель - всегда завершать последний запущенный поток -> Всегда должен быть только один запущенный doit() Функция.

Что я пытался: Как остановить цикл в Python ?

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

Этот код (с измененной функцией doit) работал для меня, чтобы остановить поток через 5 секунд. но я не могу вызвать t.do_run = False, прежде чем я начну новый поток ... Это довольно очевидно, потому что он не определен ...

Кто-нибудь знает, как остановить последний запущенный поток и начать новый?

Спасибо;)

1 Ответ

0 голосов
/ 27 марта 2020

Я думаю, вы можете решить, когда прекратить выполнение потока изнутри потока самостоятельно. Это не должно создавать никаких проблем для вас. Вы можете подумать о подходе менеджера потоков - что-то вроде ниже

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)

Теперь я попытался создать контроллер для вызова потока DoIt. Это единственный подход для достижения того, что вам нужно.

...