如何修改Telegram Bot代码实现多用户并行访问并有序存储用户答案
核心问题根源
- 你同时运行了多个
GetUpdates死循环,Telegram Bot API的offset是全局唯一的,多个循环争抢offset会直接导致消息丢失、处理阻塞 - 在
BotOnMessage的switch分支里直接await AnonymEN(),等于主消息循环被挂起,必须等AnonymEN完全执行完才会处理下一条消息,自然会出现多用户阻塞的情况 AnonymEN执行完后递归调用BotOnMessage,会导致循环嵌套层数越来越高,存在极高的内存泄漏风险
修复方案
1. 统一全局消息入口,移除嵌套的拉取消息逻辑
整个Bot只保留一个全局的GetUpdates死循环,所有用户消息都在这一个循环里处理,不要在AnonymEN、AnonymGR这类业务方法里再单独开拉取消息的逻辑。
2. 新增用户会话状态标记
你现在的ConcurrentDictionary仅存储了用户答案,补充用户当前的会话阶段字段,实现每个用户的问答流程独立跟踪:
// 定义用户会话状态枚举 enum UserState { Idle, // 初始空闲状态 ChoosingLanguage, ChoosingENOption, EnteringENName, EnteringENAge // 德语对应流程的状态可自行补充 } // 调整存储结构,同时存会话状态和用户答案 class UserSession { public UserState CurrentState { get; set; } public string[] Answers { get; set; } } static readonly ConcurrentDictionary<int, UserSession> UserSessions = new ConcurrentDictionary<int, UserSession>();
3. 重构消息处理逻辑,按用户状态分流
所有消息处理逻辑都放到唯一的主循环中,拿到消息后先查询对应用户的会话状态,再走对应业务分支:
async static Task BotOnMessage() { int offset = 0; int timeout = 10; // 建议设为10-30,减少空轮询频率 await bot.SetWebhookAsync(""); while (true) { var updates = await bot.GetUpdatesAsync(offset, timeout); foreach (var update in updates) { var message = update.Message; if (message?.Type != MessageType.Text) { offset = update.Id + 1; continue; } int userId = (int)message.From.Id; // 无会话则自动初始化 var session = UserSessions.GetOrAdd(userId, _ => new UserSession { CurrentState = UserState.Idle, Answers = Array.Empty<string>() }); switch(session.CurrentState) { case UserState.Idle: HandleIdleState(message, session); break; case UserState.ChoosingENOption: HandleENOptionState(message, session); break; case UserState.EnteringENName: HandleENNameState(message, session); break; case UserState.EnteringENAge: HandleENAgeState(message, session); break; // 其他状态对应的处理方法自行补充 } offset = update.Id + 1; } } }
4. 拆分业务逻辑,移除阻塞调用
把原来AnonymEN里的逻辑拆成对应状态的处理方法,比如输入姓名、输入年龄的逻辑分别放到对应的状态处理方法中,不要await任何会阻塞主循环的方法,所有业务处理都是单次消息响应,执行完直接回到主循环处理下一条消息。
5. 会话结束后直接重置状态
用户完成所有问答提交后,直接删除对应用户的会话或者把状态改回Idle即可,不需要递归调用BotOnMessage,主循环会自动处理后续的用户消息。
额外优化点
- 不要共用全局的
createdDateNoTime变量,每个用户的提交时间取当前实时时间即可,避免多用户并发时时间错乱 - 给会话增加过期时间,定期清理超过24小时无操作的会话,避免内存占用持续升高
内容的提问来源于stack exchange,提问作者coxcoxgo
相关产品推荐
相关产品推荐

