Почему использование асинхронного телебота приводит к увеличению количества потоков?

Почему при запуске этого кода сначала выводится 1 в консоль каждую секунду, а затем, после нажатия кнопки "Баланс", начинается вывод 2 каждую секунду, и так далее? Почему предыдущий процесс не завершается, а продолжает выполняться параллельно с новыми действиями?
  • 19 января 2024 г. 12:59
Ответы на вопрос 2
Из вашего запроса можно предположить, что речь идет о библиотеке для создания ботов для мессенджера Telegram, например, `aiogram` (асинхронный фреймворк на Python) или похожей. Как правило, асинхронные телеботы используют асинхронное программирование, которое позволяет выполнять несколько задач "одновременно" в рамках одного потока исполнения.

Асинхронный код обычно использует `event loop` для управления выполнением задач. Когда одна задача ожидает (например, ответа от сервера или ввода пользователя), loop может переключиться на другую задачу, которая готова к выполнению, тем самым используя время ожидания более эффективно, чем в случае с блокирующим кодом.

Тем не менее, если вы заметили увеличение количества потоков, это может быть связано с некоторыми асинхронными операциями, которые используют многопоточность внутри. Например, библиотека может создавать отдельные потоки для ввода-вывода или для выполнения блокирующих операций. Это делается для того, чтобы не блокировать `event loop` и позволить асинхронному коду оставаться отзывчивым.

Что касается второй части вашего вопроса, описанное поведение может быть результатом постоянного создания новых корутин (или асинхронных задач) при каждом нажатии кнопки "Баланс" без остановки или отмены предыдущих. Это может происходить следующим образом:

1. При старте бота запускается корутина (или задача), которая печатает `1` каждую секунду.
2. Когда пользователь нажимает кнопку "Баланс", запускается новая корутина, которая печатает `2` каждую секунду.
3. Поскольку предыдущая корутина не останавливается и не отменяется автоматически, обе корутины теперь работают параллельно.

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

Для устранения этой проблемы вы можете отменять предыдущую корутину перед запуском новой, сохраняя ссылку на нее, например:

```python
previous_task = None

async def on_balance_button_click():
    global previous_task
    if previous_task:
        previous_task.cancel()  # Отменяем предыдущую задачу перед запуском новой
    previous_task = asyncio.create_task(new_coroutine())
```

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