locked
Problem with speech sequence activities. RRS feed

  • Question

  •  

    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.

    Thursday, May 8, 2008 3:33 PM

Answers

  •  

    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.

    Friday, May 16, 2008 3:43 PM

All replies

  •  

    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.

    Friday, May 16, 2008 3:43 PM
  • 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.

     

     

    Friday, August 1, 2008 12:42 PM
  • 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.

     

    Sunday, August 3, 2008 12:38 AM
  • Thanks for your detailed reply.  Glad you got it sorted in the end.  Sorry about my delay in responding.

     

    Monday, August 4, 2008 8:28 AM