You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#开发Telegram Bot遇单用户阻塞,其他用户无法使用求排查

问题排查与解决方案

问题根源

  • 阻塞线程池的无限循环:在HandleUpdateAsync方法内部,你写了while (true)的无限循环,并且用.Result同步调用GetUpdatesAsync,直接阻塞了当前处理请求的线程池线程。Telegram.Bot的StartReceiving依赖线程池处理并发更新,一旦线程被这个循环占死,其他用户的消息就无法得到处理。
  • 重复轮询更新:StartReceiving已经完成了更新轮询和分发工作,手动调用GetUpdatesAsync属于重复操作,不仅无意义,还会导致更新处理逻辑混乱、占用资源。
  • 未正确处理CallbackQuery:当前HandleUpdateAsync只处理Message类型的更新,但内联键盘点击会触发CallbackQuery类型的更新,你需要直接在HandleUpdateAsync中处理这类更新,而非手动轮询获取。

修改后的代码

Business类的MainMethod和HandleUpdateAsync调整

public async Task MainMethod()
{
    var botClient = new TelegramBotClient("token");            
    using CancellationTokenSource cts = new();

    ReceiverOptions receiverOptions = new()
    {
        // 明确允许需要处理的更新类型,包含消息和回调查询
        AllowedUpdates = new[] { UpdateType.Message, UpdateType.CallbackQuery }
    };

    botClient.StartReceiving(
        updateHandler: HandleUpdateAsync,
        pollingErrorHandler: HandlePollingErrorAsync,
        receiverOptions: receiverOptions,
        cancellationToken: cts.Token
    );

    var me = await botClient.GetMeAsync();
    Console.WriteLine($"Start listening for @{me.Username}");
    Console.ReadLine();
    cts.Cancel();
}

async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
    // 处理普通消息(如/start命令)
    if (update.Message is { } message && message.Text is { } messageText)
    {
        var chatId = message.Chat.Id;
        Console.WriteLine($"Received a '{messageText}' message in chat {chatId}.");

        switch (messageText)
        {
            case "/start":
                await StartMessage(botClient, chatId, cancellationToken);
                break;
            default:
                break;
        }
    }
    // 处理内联键盘的回调查询
    else if (update.CallbackQuery is { } callbackQuery)
    {
        var chatId = callbackQuery.Message.Chat.Id;
        var callbackData = callbackQuery.Data;
        Console.WriteLine($"Received callback query '{callbackData}' from chat {chatId}.");

        // 先回复回调,避免用户看到持续加载状态
        await botClient.AnswerCallbackQueryAsync(
            callbackQueryId: callbackQuery.Id,
            cancellationToken: cancellationToken
        );

        switch (callbackData)
        {
            case "/start":
                await StartMessage(botClient, chatId, cancellationToken);
                break;
            case "BuyService":
                await BuyService(botClient, update, chatId, cancellationToken);
                break;
            // 其他回调逻辑
        }
    }
}

关键修改点说明

  1. 移除手动轮询代码:删掉HandleUpdateAsync里的无限循环和GetUpdatesAsync调用,让StartReceiving统一处理所有更新分发。
  2. 允许CallbackQuery更新:在ReceiverOptions中明确指定需要处理的更新类型,确保回调查询能被推送到处理方法。
  3. 拆分消息处理逻辑:分别处理Message和CallbackQuery类型的更新,逻辑更清晰,不会阻塞线程。
  4. 添加回调反馈:处理CallbackQuery时先调用AnswerCallbackQueryAsync,给用户的键盘点击操作提供反馈,避免无响应状态。

内容的提问来源于stack exchange,提问作者Hossein.Goodarzi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:24:58