Laden...

SpeechRecognitionEngine - Thread wird beendet

Erstellt von Big Al vor 12 Jahren Letzter Beitrag vor 12 Jahren 3.642 Views
B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 12 Jahren
SpeechRecognitionEngine - Thread wird beendet

Hallo Mycsharpler,
Viele werden noch nicht mit der Spracherkennung aus dem System.Speech.Recognition Namespace herumgespielt haben, aber vielleicht habe ich ja Glück und jemand kann mir helfen.
Ich benutze in meiner WPF Anwendung die Klasse SpeechRecognitionEngine um Sprache zu erkennen. Das funktioniert auch meistens einige Sekunden lang super. Nach zufälliger Zeit, manchmal auch sofort, beendet sich aber der Thread der Engine selbst, ohne das über irgendein Event mitzuteilen.
Wenn ich die Klasse SpeechRecognizer benutze, wird oben das Windows 7 Spracheingabefenster angezeigt, das auch immer den zuletzt gesprochenen Text zeigt. Wenn der Thread beendet ist wird dieser Text auch noch richtig angezeigt, aber keines der Events der Klasse feuert mehr.

Folgendermaßen benutze ich die Klasse:


SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine();
recognizer.SetInputToDefaultAudioDevice();

//Grammatik laden ...

recognizer.RecognizeAsync(RecognizeMode.Multiple);

In dem SpeechRecognized-Event wird einfach nur eine Action, die in einem Dictionary dem zu erkennenden Text zugeordnet ist, ausgeführt:


void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            Action<string> a;
            if (dict.TryGetValue(e.Result.Text, out a) && a != null)
                a(e.Result.Text);
        }

Das Ausgabefenster zeigt auch immer folgende Meldung an:> Fehlermeldung:

Information: 0 : SAPI does not implement phonetic alphabet selection.

Die kommt allerdings immer, auch wenn die Eingabe noch funktioniert.

Ich habe schon stundenlang nach einer Lösung gegoogelt und würde mich wirklich freuen, wenn mir hier jemand weiterhelfen könnte.
Viele Grüße,
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Big Al,

was meinst du mit "Thread der Engine selbst"? Startest du selbst irgendwelche Threads? Oder meinst du den Thread, der durch RecognizeAsync gestartet wird?

Möglicherweise handelt es sich um ein Problem mit dem GC, falls dieser am Code nicht erkennt, dass das SpeechRecognitionEngine-Objekt noch benötigt wird. In dem Fall könnte CG.KeepAlive helfen.

Ansonsten sagt die :rtfm: Doku:

Recognition failure may be due either to time out, or by a failure of the recognition engine grammar. Time out values are set by BabbleTimeout and InitialSilenceTimeout of the current instance of SpeechRecognitionEngine.

herbivore

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 12 Jahren

Hallo Herbivore,
ich meinte den Thread, der durch RecognizeAsync gestartet wurde. BabbleTimeout, InitialSilenceTimeout und EndSilenceTimeout hatte ich testweise auch auf 9 Tage gesetzt, aber das hatte nichts geholfen. Ich werden mal die Sache mit dem Garbage Collector verfolgen.
Danke sehr!
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 12 Jahren

Hallo,
ich habe alle Events, die der Recognizer hat, abonniert und keines wird mehr gefeuert, wenn der Fehler auftritt. Aber wo muss ich das KeepAlive denn einsetzen? Es sollte ja an das Ende des Codeblocks, in dem es benötigt wird. Da die Erkennung aber dauerhaft laufen soll gibt es diesen Punkt doch gar nicht so. Ich erstelle den Recognizer, starte per RecognizeAsync den "Erkennungsthread" und warte auf die Events.
Wäre die korrekte Lösung vielleicht, die synchrone Recognize() Methode in einem Thread zu benutzen und beim feuern des RecognitionCompleted-Events wieder Recognize() aufzurufen?
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.

1.820 Beiträge seit 2005
vor 12 Jahren

Hallo!

Habe zwar auch noch nie mit SpeechRecognition gearbeitet, aber das, was du zuletzt geschrieben hast (Recognize wieder aufzurufen) hätte ich jetzt auch voregeschlagen.

Ist evtl. wie bei SqlDependency, da muss man auch nach jeder Änderung den Watcher wieder neu starten.

Nobody is perfect. I'm sad, i'm not nobody 🙁

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Big Al,

Wäre die korrekte Lösung vielleicht, die synchrone Recognize() Methode in einem Thread zu benutzen und beim feuern des RecognitionCompleted-Events wieder Recognize() aufzurufen?

das wäre aber eine (potenzielle) Endlosrekursion und ist daher nicht zu empfehlen.

Da die Erkennung aber dauerhaft laufen soll gibt es diesen Punkt doch gar nicht so.

Doch, du kannst doch einfach nach dem RecognizeAsync ein WaitHandle.WaitOne aufrufen und danach das KeepAlive. Wenn du an anderer Stelle erkennst, dass die Erkennung beendet ist, rufst du WaitHandle.Set auf.

herbivore

B
Big Al Themenstarter:in
342 Beiträge seit 2006
vor 12 Jahren

Hallo,
vielen Dank Herbivore, so wie du es beschrieben hast funktioniert es bis jetzt ohne Probleme. Ich denke nicht, dass der Fehler noch auftreten wird.
Vielen Dank dafür!
Big Al

Da man Spatzen nicht mit Kanonen jagt, sollte man auch nicht mit Computern auf Spatzenhirne losgehen.