我最近进入了微软的Bot,这将是我第一次接触C#的异步编程。我正在创建一个作为选择树设计的提示符。使用一个XML文档,我设计了一个用户可以选择的主题层次结构--然后我使用一个HelpTopicSelector类抽象了这个XML的解析。
流动情况如下:
帮助对话框从基本对话框中调用如下:
private async Task ActivityRecievedAsync(IDialogContext context, IAwaitable<object> result)
{
Activity activity = await result as Activity;
if (activity.Text == "test")
{
await context.PostAsync("works");
}
else if(activity.Text == "help")
{
await context.Forward(new HelpDialog(), this.ResumeAfterHelp, activity.AsMessageActivity(), System.Threading.CancellationToken.None);
await context.PostAsync("Done Selection!");
}
context.Wait(ActivityRecievedAsync);
}我几乎可以肯定,我的代码中的问题在于我的HelpDialog的“循环”性质,但我真的不知道为什么它会失败。
class HelpDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Reached Help Dialog!");
context.Wait(ActivityRecievedAsync);
}
private async Task ActivityRecievedAsync(IDialogContext context, IAwaitable<object> result)
{
var message = await result;
await context.PostAsync("HelpDialog: Activity Received");
await HandleTopicSelection(context);
context.Wait(ActivityRecievedAsync);
}
private async Task HandleTopicSelection(IDialogContext context)
{
List<string> topics = HelpTopicSelector.Instance.Topics;
PromptDialog.Choice<string>(context, TopicSelectedAsync, topics, "Select A Topic:");
// Unecessary?
context.Wait(ActivityRecievedAsync);
}
private async Task TopicSelectedAsync(IDialogContext context, IAwaitable<string> result)
{
string selection = await result;
if (HelpTopicSelector.Instance.IsQuestionNode(selection))
{
await context.PostAsync($"You asked: {selection}");
HelpTopicSelector.Instance.Reset();
context.Done<string>(selection);
}
else
{
HelpTopicSelector.Instance.SelectElement(selection);
await HandleTopicSelection(context);
}
// Unecessary?
context.Wait(ActivityRecievedAsync);
}
}我所期望的:
考虑到这看起来是多么的烦人,我并不惊讶于面对一个错误。bot仿真器引发“堆栈为空”异常。
。在尝试使用断点进行调试之后,我注意到HelpDialog在进入HelpDialog方法时突然结束和退出(特别是当它等待结果时)。Visual引发以下异常:
无效需要:期待呼叫,有民意测验。
额外注意:,我尝试在我的BasicDialog类中编码这个逻辑,最初没有转发到任何其他对话框。令我惊讶的是,它几乎完美无缺。
发布于 2017-11-25 01:36:42
将其修改为帮助对话框:
[Serializable]
public class HelpDialog : IDialog
{
public async Task StartAsync(IDialogContext context)
{
PromptDialog.Choice<string>(context, TopicSelectedAsync, HelpTopicSelector.Instance.Topics, "Select A Topic:", attempts: 3, retry: "Please select a Topic");
}
private async Task TopicSelectedAsync(IDialogContext context, IAwaitable<object> result)
{
try
{
string selection = await result as string;
if (HelpTopicSelector.Instance.IsQuestionNode(selection))
{
await context.PostAsync($"You asked: {selection}");
HelpTopicSelector.Instance.Reset();
context.Done<string>(selection);
}
else
{
await this.StartAsync(context);
}
}
catch (TooManyAttemptsException)
{
await this.StartAsync(context);
}
}
}从这样的父对话框(使用context.Call()而不是.Forward())调用它:
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
Activity activity = await result as Activity;
if (activity.Text == "test")
{
await context.PostAsync("works");
context.Wait(MessageReceivedAsync);
}
else if (activity.Text == "help")
{
context.Call(new HelpDialog(), ResumeAfterHelp);
await context.PostAsync("Called help dialog!");
}
}
private async Task ResumeAfterHelp(IDialogContext context, IAwaitable<object> result)
{
var selection = await result as string;
context.Wait(MessageReceivedAsync);
}在为Context.Wait()提供方法时,实际上提供了一个连续委托。从用户收到的下一条消息将发送给最后一个.Wait() ed的方法。如果您正在转发,或者调用一个单独的对话框,那么父程序也不应该调用.Wait()。另外,在调用context.Done()时,也不应该在同一个对话框中出现.Wait()。
https://stackoverflow.com/questions/47476712
复制相似问题