Problem with speech sequence activities.

已答复 Problem with speech sequence activities.

  • 2008年5月8日 15:33
     
     

     

    Hi,

     

    I noticed a strange behavior with creating a SpeechSequenceActivity-derived activity. If I put a breakpoint in its constructor, it gets hit multiple times(even though I only have one instance on my main workflow). Also, the same behavior is repeated for Initialize method. Is there any reason for that? What is the recommended way for executing initialization code in SpeechSequence activities?

     

     

    Thanks in advance.

全部回复

  • 2008年5月16日 15:43
     
     已答复

     

    If anybody's having the same problem, I found a workaround. I am putting my initalization code in overridden Execute method:

     

    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

    {

    mainMenu.Closed += new EventHandler<ActivityExecutionStatusChangedEventArgs>(MainMenu_Closed);

    return base.Execute(executionContext);

    }

    This solves the problem of your event registration code running multiple times in the constructor.

  • 2008年8月1日 12:42
     
     

    Workflow does create multiple instances of your workflow.  This is normal. 

     

    For a given instance, the constructor can only be executed once.  Therefore, it is safe to put any initialisation code into the constructor that is unique to the instance, e.g. event subscriptions.  If you look at the auto-generated code, this is precisely what it does, inside InitializeComponent, which is invoked from your constructor.

     

    When you refer to the Initialize method, do you mean InitializeComponent?  This is invoked from the constructor, so again you will see it invoked multiple times, but only once per instance.

     

    I.e. I think you're trying to solve a problem that doesn't exist.

     

     

  • 2008年8月3日 0:38
     
     

    Well, if you have replied to it back in May(when the original question was posted), I would probably have explained what I was experiencing in details. Perhaps, I wasn’t clear on the problem. When I talked about initialization, I meant event registration code. To understand the problem, consider this simple IVR. Workflow has one custom speech sequence activity. The custom activity contains a QuestionAnswerActivity and a StatementActivity. Basically, it asks you to say a number and  statement will repeat the number. Custom Speech Sequence activity code is below:

        public sealed partial class VoiceResponseSequenceActivity1 : SpeechSequenceActivity

        {

            private string number;

            public VoiceResponseSequenceActivity1()

            {

                InitializeComponent();

                questionAnswerActivity1.Grammars[0].Recognized += new EventHandler<RecognizedEventArgs>(VoiceResponseSequenceActivity1_Recognized);

                statementActivity1.TurnStarting += new EventHandler<TurnStartingEventArgs>(statementActivity1_TurnStarting);

            }

     

            void VoiceResponseSequenceActivity1_Recognized(object sender, RecognizedEventArgs e)

            {

                number = e.Result.Semantics.Value.ToString();

            }

     

            private void statementActivity1_TurnStarting(object sender, TurnStartingEventArgs e)

            {

                statementActivity1.MainPrompt.SetText(number);

            }

    The behavior I noticed was that it would hit the constructor multiple times. Then when the Recognized gets triggered, it would set the number  field. However, when I accessed the field in statementActivity1’s TurnStarting event handler, it was always null. My initial assumption was that those two events were being registered in separate clones and there was no correlation between them. The question was asked under that assumption. And when I tried putting the event registration code in overridden Execute, this was no longer an issue. So we thought the problem was solved that way(it partially was). However, recently I found out how to properly handle these situations. This was happening because when ActivityExecutionContext clones the activities and changes made in those cloned activities can be propogated to the original one by making those values InstanceDependencyProperties. So if I declared my number value as following, it would have solved it as well:

     

    public static InstanceDependencyProperty NumberProperty = InstanceDependencyProperty.Register("Number", typeof(string), typeof(VoiceResponseSequenceActivity1));

            public string Number

            {

                get { return (string)GetValue(NumberProperty); }

                set { SetValue(NumberProperty, value); }

            }

    As for your comments on Initialize method, I did mean Initialize(inherited from Activity class) not InitializeComponent. So yeah, problem did exist, at least for me because it was preventing me from going forward on the project.

     

  • 2008年8月4日 8:28
     
     
    Thanks for your detailed reply.  Glad you got it sorted in the end.  Sorry about my delay in responding.