3

Using MSDN's SAPI, how do you cancel a synchronous speech recognition operation, or at least stop it immediately?

Setting the input to null returns an error saying that I can't do that while the recognizer is recognizing, and using Asynchronous recognition is not an option.

Here is an example below

class MainClass {

     static void Main( ) {
          SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine();
          recognizer.LoadGrammar(new DictationGrammar() );
          recognizer.SetInputToDefaultAudioDevice();
          recognizer.Recognize();
     }

     void MethodCalledFromOtherThread() {   
           //Since SpeechRecognitionEngine.Recognize() stops the current thread,
           //this method is called from a different thread.
           //I NEED the current thread to stop.

           //Here I want to Cancel recognizer.Recognize     
      }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
JackBarn
  • 635
  • 1
  • 6
  • 18
  • 1
    You _might_ be able to get hold of the original thread and throw an exception on it, but [this question](http://stackoverflow.com/questions/44656/is-there-a-good-method-in-c-sharp-for-throwing-an-exception-on-a-given-thread) covers why you shouldn't do that. Can you explain why the async option doesn't work for you, given that that has a specific method for cancelling? – James Thorpe Apr 02 '15 at 14:43
  • @JamesThorpe The way my application works and is set up, an Async operation would be to costly in terms of performance – JackBarn Apr 02 '15 at 14:51
  • By it's nature you can't cancel a sync call. Is there a Beginxxx, Endxxx version of the functions that you could use? – John Taylor Apr 02 '15 at 15:11
  • @John Taylor What do you mean "the functions" – JackBarn Apr 02 '15 at 19:45
  • 1
    There's no point whatsoever in using Recognize() when you can use RecognizeAsync(). Which is trivially cancelled with RecognizeAsyncCancel(). – Hans Passant Apr 03 '15 at 00:21

1 Answers1

3

This MSDN article shows how to use SAPI asynchronously without a thread and with this you can cancel the operation at anytime.

Here is a very simple example of how to terminate the recognition early.

class Program
{
    private static bool _userRequestedAbort = false;

    // Indicate whether asynchronous recognition is complete.

    static void Main(string[] args)
    {
        // Create an in-process speech recognizer.
        using (SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(new CultureInfo("en-US")))
        {
            // Create a grammar for choosing cities for a flight.
            Choices cities = new Choices(new string[] { "Los Angeles", "New York", "Chicago", "San Francisco", "Miami", "Dallas" });

            GrammarBuilder gb = new GrammarBuilder();
            gb.Append("I want to fly from");
            gb.Append(cities);
            gb.Append("to");
            gb.Append(cities);

            // Construct a Grammar object and load it to the recognizer.
            Grammar cityChooser = new Grammar(gb);
            cityChooser.Name = ("City Chooser");
            recognizer.LoadGrammarAsync(cityChooser);

            bool completed = false;

            // Attach event handlers.
            recognizer.RecognizeCompleted += (o, e) =>
            {
                if (e.Error != null)
                {
                    Console.WriteLine( "Error occurred during recognition: {0}", e.Error);
                }
                else if (e.InitialSilenceTimeout)
                {
                    Console.WriteLine("Detected silence");
                }
                else if (e.BabbleTimeout)
                {
                    Console.WriteLine("Detected babbling");
                }
                else if (e.InputStreamEnded)
                {
                    Console.WriteLine("Input stream ended early");
                }
                else if (e.Result != null)
                {
                    Console.WriteLine("Grammar = {0}; Text = {1}; Confidence = {2}", e.Result.Grammar.Name, e.Result.Text, e.Result.Confidence);
                }
                else
                {
                    Console.WriteLine("No result");
                }

                completed = true;
            };

            // Assign input to the recognizer and start an asynchronous
            // recognition operation.
            recognizer.SetInputToDefaultAudioDevice();

            Console.WriteLine("Starting asynchronous recognition...");
            recognizer.RecognizeAsync();

            // Wait for the operation to complete.
            while (!completed)
            {
                if (_userRequestedAbort)
                {
                    recognizer.RecognizeAsyncCancel();
                    break;
                }

                Thread.Sleep(333);
            }

            Console.WriteLine("Done.");
        }

        Console.WriteLine();
        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}
John Taylor
  • 446
  • 3
  • 8
  • 1
    Link-only answers are insufficient on stackoverflow. – Sildoreth Apr 02 '15 at 20:28
  • 1
    Okay, I will add some value shortly and not just cut & paste – John Taylor Apr 02 '15 at 20:34
  • Thanks Alot. The reason I was not using Async was because it allowed the main thread to keep running but I never thought about this. I substituted `Join()` with `Suspend()` and now everything works as I want it to – JackBarn Apr 03 '15 at 00:41