Как остановить telegram бота

Предположим у нас есть такой код:

public Bot() { }

private static string tokenToAPI = "<token>";

private static ITelegramBotClient? _botClient;

// Это объект с настройками работы бота. Здесь мы будем указывать, какие типы Update мы будем получать, Timeout бота и так далее.
private static ReceiverOptions? _receiverOptions;

public async Task Run()
{

    _botClient = new TelegramBotClient(tokenToAPI);
    _receiverOptions = new ReceiverOptions
    {
        AllowedUpdates = new[]
        {
        UpdateType.Message
    },
        ThrowPendingUpdates = false,
    };

    using CancellationTokenSource cts = new CancellationTokenSource();

    _botClient.StartReceiving(UpdateHandler, ErrorHandler, _receiverOptions, cts.Token); // Запускаем бота

    User bot = await _botClient.GetMeAsync();

    Notifier.SendNote($"Бот ` {bot.Username} ` успешно запущен и инициализирован\n");
    Notifier.SendBoolean(true);

    await Task.Delay(-1); // Устанавливаем бесконечную задержку, чтобы наш бот работал постоянно

}

И вот пара методов:

private static async Task UpdateHandler(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
    try
    {
        switch (update.Type)
        {
            case UpdateType.Message:
                {
                    // Какая-то логика

                    return;
                }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

private static Task ErrorHandler(ITelegramBotClient botClient, Exception error, CancellationToken cancellationToken)
{
    // Тут создадим переменную, в которую поместим код ошибки и её сообщение 
    string ErrorMessage = error switch
    {
        ApiRequestException apiRequestException
            => $"Telegram API Error:\n[{apiRequestException.ErrorCode}]\n{apiRequestException.Message}",
        _ => error.ToString()
    };

    Console.WriteLine(ErrorMessage);
    return Task.CompletedTask;
}

Буквально код из Хабра

Мой вопрос состоит в следующем: каким образом можно написать такой метод (не обязательно в этом же классе), который полностью остановит бота. После вызова такого метода бот не должен проявлять признаки жизни и для повторного его запуска нужно будет вызвать метод Run()


Ответы (1 шт):

Автор решения: aepot

Например с помощью TaskCompletionSource.

private TaskCompletionSource tcs;

public async Task Run()
{
    if (tcs is not null)
        throw new InvalidOperationException("Bot is already running.");
    tcs = new();

    // убираем await Task.Delay(-1);
    // добавляем вот это
    await tcs.Task;
    tcs = null;
    // здесь можно выполнить все остановки, какие требуются, например:
    cts.Cancel();
}

public void Stop()
{
    tcs?.SetResult() ?? throw new InvalidOperationException("Bot is not running.");
}
→ Ссылка