Отмена задачи Python Asyncio из другого цикла событий - PullRequest
0 голосов
/ 06 июня 2019

Я думаю, что проблема связана с циклами событий и вызовом отмены из цикла событий, отличного от того, в котором он был создан. Код, который, по моему мнению, вызывает проблему, - это синхронный метод, который передается в клиентскую библиотеку.который подключается к внешнему источнику, когда внешний источник теряет соединение, он вызывает этот метод.

Проблема в том, что методы stop и start являются асинхронными и работают сами по себе, метод start создается взадача, и он ждет окончания сна, затем вызывает стоп, который отменяет задачу и, кажется, работает нормально, из метода синхронизации мне нужно создать новый цикл событий для вызова остановки, который также работает, но, хотя вы можете вызвать отмену, задача никогда не кажетсязакрыть, и я получаю желаемый результат переподключения только после того, как сон закончился.Если я напечатаю переменную self._task до и после, она покажет, что она была отменена, но она явно продолжает работать.

<Task pending coro=<AsyncAKSServer.start() running at aks_server.py:88> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f551e268f18>()]> cb=[<TaskWakeupMethWrapper object at 0x7f551e268e58>()]>
<Task pending coro=<AsyncAKSServer.start() running at aks_server.py:88> wait_for=<Future cancelled> cb=[<TaskWakeupMethWrapper object at 0x7f551e268e58>()]>

К сожалению, я не могу дать точный код по причинам IP, но ниже приведенВ примере, показывающем, что я пытаюсь сделать, я не могу обновить клиентскую библиотеку, в которую в настоящее время отправляется метод синхронизации, так как мы находимся в нерабочем периоде, поэтому изменение на асинхронное невозможно.Есть реальный шанс, что я неправильно понял документы, и как это должно работать, любая помощь приветствуется.

import asyncio

class AsyncServer:
    def __init__(self):
        self._task = None
        self._duration = 1

    async def run(self):
        while True:
            self._task = asyncio.create_task(self.start())
            try:
                await self._task
            except asyncio.CancelledError:
                print('Start task cancelled')

    async def start(self):
        await asyncio.sleep(self._duration)
        await self.stop()

    async def stop(self):
        self._taks.cancel()

    def sync_request(self):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(self.stop())
        loop.stop()
        loop.close()

def main():
    server = AsyncServer()
    asyncio.run(server.run())

1 Ответ

0 голосов
/ 06 июня 2019

Эта проблема действительно вызвана необходимостью создания нового цикла событий, исправление которого заключается в сохранении ссылки на цикл событий в методе start.Затем вы можете использовать это для вызова asyncio.run_coroutine_threadsafe(self.stop(), self._loop), который пропускает тот же цикл и заставляет отмену работать должным образом.

...