You must properly shut down speech recognizers when your application exits.
SpeechRecognizer eventing APIs must be torn down in an ordered fashion to prevent application hangs on exit. The correct pattern is summarized below.
For SpeechRecognizer APIs specifically, the aforementioned problem applies to both SpeechRecognizer.RecognizeAsync Method and ContinuousRecognition APIs. To ensure deterministic closing, the caller must tell the SpeechRecognizer Class to cease processing and then wait to be signaled that it is complete. The following APIs allow a client to cease the SpeechRecognizer’s processing:
// Continuous recognition consumers should call StopContinuousRecognition
ISpeechRecognizer::StopContinuousRecognition();
// RecognizeAsync consumer should call cancel
IAsyncOperation<SpeechRecognitionResult>::Cancel();
The caller then must wait for the completion of the asynchronous event – a completion of IAsyncOperation with one of the following ContinuousSpeechRecognitionStatus Enumeration values for continuous recognition: Stopped, Completed, or Error.
The following sample code demonstrates the correct pattern for use with continuous recognition eventing. If your application consumes speech from multiple threads then synchronization between the recognizer state is also required. The following example assumes a single application thread, but be aware that HandleLocalRecognitionStatusChange will be called on a separate COM invoking thread.
void Application::HandleLocalRecognitionStatusChange(ContinuousSpeechRecognitionStatus status)
{
// The following events are all terminal events
if (status == Stopped || status == Completed || status == Error)
{
_recognizerRunning = false;
}
else
{
_recognizerRunning = true;
}
if (!_isClosing)
{
// Normal handling
}
else
{
if(!_recognizerRunning)
{
::SetEvent(_closeEvent);
}
// Else do nothing, wait until we get a terminal event
}
}