Bot多对话场景Stop指令触发后KeyNotFoundException问题求助
解决Bot Framework中退出指令后发送消息出现KeyNotFoundException的问题
错误原因分析
你遇到的KeyNotFoundException是因为调用context.Done(true)后,RootDialog的对话生命周期已经被彻底结束,对应的会话状态被标记为已完成。当用户发送下一条消息时,Conversation.SendAsync会尝试从持久化存储中恢复之前的对话会话,但这个会话已经不存在了,所以抛出了找不到键的异常。
解决方案
根据你的需求,有两种合适的处理方式:
1. 彻底结束对话,允许用户下次启动新对话
如果你希望用户发送退出指令后,整个对话完全结束,下次发消息时启动全新的对话,把context.Done(true)替换为context.EndConversationAsync():
public override async Task StartAsync(IDialogContext context) { string[] stopStrings = { "quit", "cancel", "exit" }; var msg = context.Activity.AsMessageActivity().Text; if (stopStrings.Any(s => msg.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0)) { await context.PostAsync("You cancelled."); await context.EndConversationAsync(); // 结束整个对话会话 } else { context.Wait(this.MessageReceived); } }
这里还优化了退出词汇的检测逻辑,改成不区分大小写的匹配,避免用户输入"Quit"或"EXIT"时无法触发退出。
2. 保持对话活跃,允许用户继续交互
如果你只是想让用户退出当前流程,但仍能继续和Bot对话,不要结束RootDialog,而是重新等待下一条消息:
public override async Task StartAsync(IDialogContext context) { string[] stopStrings = { "quit", "cancel", "exit" }; var msg = context.Activity.AsMessageActivity().Text; if (stopStrings.Any(s => msg.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0)) { await context.PostAsync("You cancelled. I'm ready for your next request."); context.Wait(this.MessageReceived); // 保持对话活跃,等待新消息 } else { context.Wait(this.MessageReceived); } }
这种方式下,对话会话会一直保持活跃,用户后续发送的消息能正常被Bot处理。
额外说明
context.Done<T>()的作用是完成当前对话框的执行,并将结果返回给父对话框。由于RootDialog是根对话框,没有父对话框,调用它会直接结束整个对话会话的状态,导致后续无法恢复,这就是你遇到异常的核心原因。
内容的提问来源于stack exchange,提问作者Kraishan
相关产品推荐
相关产品推荐

