0

I'm trying to:

  1. Say something with TTS
  2. Wait asynchronously until the text has finished
  3. Wait asynchronously a while
  4. Return to the start

I have managed to do this, but it feels like a work-around as I am forced to put code in the synthesizer_SpeakCompleted method. My code so far is below. I would appreciate any info on the right way to do this.

public void TestDelay()
{
    DoSomeSpeechAndSignalWhenItsDone();
}

public void DoSomeSpeechAndSignalWhenItsDone()
{
    form.AccessTxtQnReport += "This is written before the speech" + Environment.NewLine;
    synthesizer.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(synthesizer_SpeakCompleted);
    synthesizer.SpeakAsync("this is a load of speech and it goes on quite a while");
}

async void  synthesizer_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
{
    //we get here when speech has finished
    form.AccessTxtQnReport += "This is written after the speech" + Environment.NewLine;
    synthesizer.SpeakCompleted -= new EventHandler<SpeakCompletedEventArgs>(synthesizer_SpeakCompleted);

    // Do a delay
    await Task.Delay(3000);
    form.AccessTxtQnReport += "This is written after the delay" + Environment.NewLine;
    // this makes it cycle round for ever
    TestDelay();
}

EDIT > Thanks for the responses. I have now changed the code to this which seems to work, and looks a bit nicer:

// attempt delay using TaskCompletionSource
private TaskCompletionSource<bool> tcs;
public void TestDelay()
{
    tcs = new TaskCompletionSource<bool>();
    DoSomeSpeechAndSignalWhenItsDone();
}

private async void DoSomeSpeechAndSignalWhenItsDone()
{          
    form.AccessTxtQnReport += "This is written before the speech" + Environment.NewLine;
    synthesizer.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(synthesizer_SpeakCompleted);
    synthesizer.SpeakAsync("this is a load of speech and it goes on quite a while");
    await tcs.Task;

    form.AccessTxtQnReport += "This is written after the speech" + Environment.NewLine;
    await Task.Delay(2000);
    form.AccessTxtQnReport += "This is written after the delay" + Environment.NewLine;

    // repeat the process ad nauseam
    TestDelay();
}

private  void synthesizer_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
{
    //we get here when speech has finished         
    synthesizer.SpeakCompleted -= new EventHandler<SpeakCompletedEventArgs>(synthesizer_SpeakCompleted);
    //set the task as completed:
    tcs.SetResult(true);          
}
GordonBooker
  • 45
  • 1
  • 7
  • Why don't you `await SpeakAsync()` and then `await Task.Delay()`? – zmbq Mar 26 '17 at 18:34
  • 2
    @zmbq Because [`SpeakAsync`](https://msdn.microsoft.com/en-us/library/ms586891(v=vs.110).aspx) does not return a `Task`. – GSerg Mar 26 '17 at 18:35
  • 3
    Follow the advice of using `TaskCompletionSource` in the linked duplicate. See also [this article](https://msdn.microsoft.com/en-us/library/ee622454(v=vs.110).aspx) on how to convert a Event-Based Asynchronous Pattern (EAP) like you have to a task. – Scott Chamberlain Mar 26 '17 at 18:45
  • Thanks for the responses, and the very useful link to the duplicate. I have changed my code and edited my post accordingly. – GordonBooker Mar 28 '17 at 07:09
  • 1
    The *correct* place to put a solution is as an answer, not as an edit to your question. I'm not sure I'd do *either* though when the question has been closed, as here. – Damien_The_Unbeliever Mar 28 '17 at 07:14

0 Answers0