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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:36:53