Botframework v4:从子对话框调用父对话框,而没有stackoverflow异常 [英] Botframework v4: Call parent dialog from child dialog without stackoverflow exception

查看:94
本文介绍了Botframework v4:从子对话框调用父对话框,而没有stackoverflow异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据,我认为现在可以打电话给父母了子对话框中的对话框.在我不能这样做之前,因为它将导致堆栈溢出异常.我已经更新到SDK 4.3,有人知道如何实现此更改吗?

According to this i think it is possible now to call the parent dialog from a child dialog. Before i can't do that because it will cause a Stack overflow exception. I've already updated to SDK 4.3 does anyone know how to implement this changes?

主对话框调用对话框A.

Main dialog calls dialog A.

WaterfallStep[] waterfallSteps = new WaterfallStep[]
     {
        FirstStepAsync,
        SecondStepAsync,
        ThirdStepAsync,
     };
    AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
    AddDialog(new DialogA(DialogAId));

  return await stepContext.BeginDialogAsync(DialogAId, cancellationToken: cancellationToken);

对话框A调用对话框Achild

Dialog A calls Dialog Achild

    WaterfallStep[] waterfallSteps = new WaterfallStep[]
     {
        FirstStepAsync,
        SecondStepAsync,
        ThirdStepAsync,
     };
    AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
    AddDialog(new DialogAchild(DialogAchildId));

   return await stepContext.BeginDialogAsync(DialogAchildId, cancellationToken: cancellationToken);

Dialog Achild调用MainDialog,但这会产生堆栈溢出异常.

Dialog Achild calls MainDialog, but this will produce a Stack overflow exception.

WaterfallStep[] waterfallSteps = new WaterfallStep[]
     {
        FirstStepAsync,
        SecondStepAsync,
        ThirdStepAsync,
     };
    AddDialog(new WaterfallDialog(InitialId, waterfallSteps));
    AddDialog(new MainDialog(MainDialogId));

  return await stepContext.BeginDialogAsync(MainDialogId, cancellationToken: cancellationToken);

推荐答案

假定您在对话框的构造函数中添加了Dialogs,那么您将产生一个无限循环,最终导致所描述的堆栈溢出.

Assuming you're adding the Dialogs in the constructor of your dialog, then you're producing an infinite loop ultimately resulting in the stack overflow you're describing.

MainDialog --> DialogA --> DialogAchild --> MainDialog --> infinite loop

您提到的PR是一个稍微不同的问题.

The PR you're mentioning refers to a slightly different problem.

解决此问题的一种方法是从构造函数中删除导致最终循环的AddDialog方法.而是将调用移至类似AddDialogA()的方法,并仅在需要时调用它.

One way to work around this is to remove the AddDialog method causing the final loop from the constructor. Instead, move the call to a method like AddDialogA() and call it only if needed.

根据您的情况,您可以构建一个提供此类功能的基本对话框.

Based on your scenario, you could build a base dialog offering this kind of functionality.

以下是AuthenticatedDialog的示例,可让您在必要时添加OnboardingDialog.请注意,上载对话框"本身是从AuthenticatedDialog继承的,当您不卸载AddDialog()调用时,这也会引起无限循环.

Here is a sample of an AuthenticatedDialog offering you to add an OnboardingDialog when necessary. Note that the Onboarding Dialog itself inherits from AuthenticatedDialog which would cause an infinite loop as well when you're not offloading the AddDialog() call.

在基本对话框中对此进行抽象很不错,因为它为您提供了一些可以使用的API.考虑命名您的东西,例如AddComponentDialog或UseComponentDialog.这样,您就可以很好地表达自己的意图,并且潜在的读者可以一开始就知道您正在使用可重复使用的组件.

Abstracting this in base dialogs is nice, because it gives you a little API you can use. Consider naming your stuff like AddComponentDialog or UseComponentDialog. This way you're expressing your intend quite good and a potential reader knows initally that you're using re-usable components.

AuthenticatedDialog.cs

using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Schema;
using Bot.Dialogs.Authentication;
using Bot.Dialogs.Main;
using Bot.Dialogs.Onboarding;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Bot.Dialogs.Shared
{
    public class AuthenticatedDialog : EnterpriseDialog
    {
        private BotStateAccessors _accessors;
        private BotServices _botServices;

        public AuthenticatedDialog(BotServices botServices, string dialogId, BotStateAccessors accessors) : base(botServices, dialogId)
        {
            _accessors = accessors;
            _botServices = botServices;

            AddDialog(new AuthenticationDialog("", accessors));
        }

        protected async Task<DialogTurnResult> AskForOnboardingAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken, object stepResult = null)
        {
            return await stepContext.BeginDialogAsync(nameof(OnboardingDialog), stepResult, cancellationToken);
        }

        protected void AddOnboardingDialog()
        {
            AddDialog(new OnboardingDialog(_botServices,_accessors));
        }

    }
}

DialogA.cs

public class DialogA : AuthenticatedDialog
{

        public DialogA(BotServices botServices, BotStateAccessors accessors) : base(botServices, nameof(DialogA), accessors)
        {

            var preferencesDispatchSteps = new WaterfallStep[]
            {
                WaterfallStepA,
                WaterfallStepB
            };

            AddDialog(new FooDialog);
            AddOnboardingDialog();
        }
}

这篇关于Botframework v4:从子对话框调用父对话框,而没有stackoverflow异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆