Python - Threading - Убедитесь, что Timer () останавливается правильно - PullRequest
0 голосов
/ 26 октября 2018

Я хочу убедиться, что мой таймер правильно останавливается после запуска timer.cancel(), но я не уверен, правильно ли я это делаю. Насколько мне известно, сначала вы останавливаете его, запуская cancel(), а затем ждете, пока поток не будет полностью очищен и завершен, используя join(). Если я запускаю join() после отмены, любые операторы после join() будут выполняться только после полного завершения потока. Я правильно это понимаю?

Если нет, как мне убедиться, что мой поток завершен полностью, и что мои следующие строки кода будут выполняться только после завершения потока?

def f():
    timer = threading.Timer(5, f)

    if something_happens:
        timer.cancel()
        timer.join()

        do_something_after_timer_completely_stops()

1 Ответ

0 голосов
/ 26 октября 2018

Вам не нужно звонить .join().Для остановки таймера достаточно набрать .cancel().Однако есть предостережение: таймеры могут быть остановлены только в том случае, если они находятся в стадии ожидание (до истечения времени).Если реальный код уже запущен, он не может быть остановлен с помощью .cancel();Он становится обычным потоком.

Способ реализации класса threading.Timer() использует ожидаемый экземпляр threading.Event, чтобы разрешить отмену таймера, однако, если таймер заканчивается, событие устанавливается только послефункция завершена.Таким образом, вы не можете использовать его, чтобы надежно определить, запущен ли поток.Я предлагаю создать собственный объект события, если вы хотите, чтобы вас об этом уведомили.

Пример: вы создаете таймер для вызова f:

timer = threading.Timer(5, f)

Вместо этого создайте новое событиеи функцию, которая устанавливает его перед вызовом f, и запланируйте таймер для вызова созданной вами новой функции.

f_called = threading.Event()
def calls_f(*args, **kwds):
    """function that calls f after setting the event f_called"""
    f_called.set()
    return f(*args, **kwds)

timer = threading.Timer(5, calls_f)

Затем вы можете использовать это событие, чтобы проверить, был ли уже вызван f:

if f_called.is_set():
     print("Too bad, thread is already running, can't cancel the timer!")
...