Как приостановить созданную Asyncio задачу, используя блокировку или другой метод? - PullRequest
0 голосов
/ 10 апреля 2020

Это пример программы, которую я пытаюсь сделать в главном проекте, но основная идея заключается в том, что я создал задачу, используя asyncio.create_task. Я хочу затем приостановить эту задачу позже в коде, когда происходит какое-то событие. В этом примере кода asyncio.create_task запускает task_tic_tock и печатает «ti c -tock». Позже в коде, когда other_task имеет счетчик, который делится на 3, он берет блокировку и запускает task_tic_tock с параметром False. Я не уверен, что блокировка - это лучшее, что нужно использовать, но я надеюсь, что он выведет «In new count» и «print val is false», но не «ti c -» tock ". Как только блокировка закончится, я хочу возобновить печать" tic_tock ".

import asyncio

lock = asyncio.Lock()

def task_tic_tock(print_val):
    if print_val:
        print("tic-tock")
    else:
        print("Print val is now false")

async def start_tic_tock(print_val):
    while True:
        task_tic_tock(print_val)
        await asyncio.sleep(1)

async def other_task():
    count = 0
    while True:
        count = count + 1
        if count % 3 == 0:
            async with lock:
                task_tic_tock(False)
                new_count = 5
                while new_count > 0:
                    print("In new count")
                    new_count = new_count - 1
                    await asyncio.sleep(1)
        await asyncio.sleep(1)
    print("Other task running")
    await asyncio.sleep(1)

async def main():
    print_val = asyncio.create_task(start_tic_tock(True))
    await asyncio.gather(other_task(), print_val)


asyncio.run(main())

Как работает create_task и возможно ли приостановить его на некоторое время, пока выполняется другая задача? Любая помощь был бы оценен!

1 Ответ

1 голос
/ 11 апреля 2020

Вы можете достичь того, что вы хотите с замком. Проблема с вашим кодом заключается в том, что вы никогда не получаете блокировку в start_tic_tock, поэтому у вас нет возможности «приостановить» эту сопрограмму на основе блокировки, полученной в other_task.

. чтобы ваш start_tic_tock метод получил блокировку следующим образом:

async def start_tic_tock(print_val):
   while True:
       async with lock:
           task_tic_tock(print_val)
           await asyncio.sleep(1)

При этом Событие может лучше соответствовать тому, что вы хотите. События явно предназначены для уведомления задач, когда условие достигнуто. Полный код ниже, используя событие. Обратите внимание, что когда вы создаете Event или Lock глобально, как вы делаете в приведенном выше коде, вы можете создавать новое событие l oop. asyncio.run всегда создает новый l oop, что означает, что вы можете запустить два цикла, что может привести к исключениям. В приведенном ниже я явно создал al oop, чтобы избежать этих ошибок, вам нужно немного изменить рефакторинг, чтобы снова использовать asyncio.run.

import asyncio

loop = asyncio.new_event_loop()
event = asyncio.Event(loop=loop)

async def start_tic_tock(print_val):
    while True:
        await event.wait()
        task_tic_tock(print_val)
        await asyncio.sleep(1)

async def other_task():
    count = 0
    while True:
        count = count + 1
        if count % 3 == 0:
            event.clear()
            task_tic_tock(False)
            new_count = 5
            while new_count > 0:
                print("In new count")
                new_count = new_count - 1
                await asyncio.sleep(1)
            event.set()
        await asyncio.sleep(1)
    print("Other task running")
    await asyncio.sleep(1)

async def main():
    print_val = asyncio.create_task(start_tic_tock(True))
    await asyncio.gather(other_task(), print_val)

loop.run_until_complete(main())

Приведенные выше отпечатки:

Print val is now false
In new count
In new count
In new count
In new count
In new count
tic-tock
tic-tock
tic-tock
...