Python: Как ждать, пока функция будет вызвана в другом потоке? - PullRequest
0 голосов
/ 02 мая 2020

У меня есть функция в потоке A, которая должна ждать, пока не будет вызвана функция в потоке B.

Функция в потоке B вызывается периодически, поэтому ей просто нужно подождать до следующего раза называется. Это позволяет мне синхронизировать c с ним.

Как бы я это сделал?

(Извините, если это тривиально.)

1 Ответ

1 голос
/ 02 мая 2020

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

Существуют различные способы сделать это, но один из самых простых - использование объекта Threading.Event. События являются простейшим из так называемых примитивов синхронизации. Обратитесь к разделу руководства по резьбовому модулю для получения дополнительной информации. Вот рабочий пример:

#! python3.8

import threading
import time

t0 = time.time()

def elapsed_time():
    return time.time() - t0

class StopMe:
    def __init__(self):
        self.running = True

def main():
    ev1 = threading.Event()
    stop = StopMe()
    th1 = threading.Thread(target=thread1, args=(ev1, stop))
    th1.start()
    for _ in range(10):
        ev1.wait()
        print("The function was just called", elapsed_time())
        ev1.clear()
    stop.running = False
    th1.join()
    print("Exit", elapsed_time())

def thread1(event, stop):
    def a_function():
        event.set()
        print("I am the function", elapsed_time())

    while stop.running:
        time.sleep(1.0)
        a_function()

main()

Вывод:

I am the function 1.0116908550262451
The function was just called 1.0116908550262451
I am the function 2.0219264030456543
The function was just called 2.0219264030456543
I am the function 3.0322916507720947
The function was just called 3.0322916507720947
I am the function 4.033170938491821
The function was just called 4.033170938491821
I am the function 5.043376445770264
The function was just called 5.043376445770264
I am the function 6.043909788131714
The function was just called 6.043909788131714
I am the function 7.054021596908569
The function was just called 7.054021596908569
I am the function 8.06399941444397
The function was just called 8.06399941444397
I am the function 9.064924716949463
The function was just called 9.064924716949463
I am the function 10.066757678985596
The function was just called 10.066757678985596
I am the function 11.076870918273926
Exit 11.076870918273926

Некоторые вещи, на которые следует обратить внимание:

После того, как вы добавили в свой код примитив синхронизации, вам нужно подумать о том, как изящно завершить поток и как завершить приложение в целом. В этом примере потоки взаимодействуют через маленький объект «StopMe» и через объект Event. Обратите внимание, что главному потоку, возможно, придется ждать одну секунду, пока вторичный поток не завершит свою функцию ожидания. Это происходит, если thread1 начинает задержку до того, как основной поток вызывает функцию join. Этого не произошло в моем тестовом прогоне, но это может произойти, в зависимости от того, как процессорные интервалы времени передаются различным потокам. Если это неприемлемо для вас, вам нужно написать больше кода, чтобы обойти это.

Также обратите внимание, что вызов функции ev1.wait () будет блокировать основной поток, пока событие не будет установлено из вторичного потока. В приложении GUI это не то, что вам нужно.

Я запустил это с Python3 .8, но программа не использует специфичные для версии функции c, поэтому она должна работать так же с любой достаточно свежей версией Python.

...