Ich habe eine asp.net MVC-Anwendung, die eine Controlleraktion hat, die eine Zeichenfolge als Eingabe verwendet und eine Antwort-WAV-Datei der synthetisierten Sprache sendet. Hier ist ein vereinfachtes Beispiel:System.Speech.Synthes hängt mit hoher CPU auf 2012 R2
public async Task<ActionResult> Speak(string text)
{
Task<FileContentResult> task = Task.Run(() =>
{
using (var synth = new System.Speech.Synthesis.SpeechSynthesizer())
using (var stream = new MemoryStream())
{
synth.SetOutputToWaveStream(stream);
synth.Speak(text);
var bytes = stream.GetBuffer();
return File(bytes, "audio/x-wav");
}
});
return await task;
}
Die Anwendung (und diese Aktion Verfahren insbesondere) läuft fein in einer Server-Umgebung auf 2008 R2 Server 2012 (nicht-R2) Server und meinen 8.1 dev PC. Es läuft auch gut auf einer standardmäßigen virtuellen Azure 2012 R2-Maschine. Wenn ich sie jedoch auf drei 2012 R2-Servern (deren endgültiges Heim) bereitstellen, erzeugt die Aktionsmethode niemals eine HTTP-Antwort - der IIS-Arbeitsprozess maximiert einen der CPU-Kerne auf unbestimmte Zeit. Es ist nichts in der Ereignisanzeige und nichts springt auf mich heraus, wenn ich den Server mit Procmon beobachte. Ich habe den Prozess mit Remote-Debugging angefügt und die synth.Speak(text)
kehrt nie zurück. Wenn der Aufruf synth.Speak(text)
ausgeführt wird, sehe ich sofort den Runaway-Prozess w3wp.exe im Task-Manager des Servers.
Meine erste Neigung war auf den Servern einige Verfahren wurden stören Sprachsynthese im Allgemeinen zu glauben, aber die Windows-Erzähler richtig funktioniert, und eine einfache Konsolenanwendung wie das funktioniert auch richtig:
static void Main(string[] args)
{
var synth = new System.Speech.Synthesis.SpeechSynthesizer();
synth.Speak("hello");
}
So offensichtlich Ich kann die Sprachsynthese des Servers im Allgemeinen nicht tadeln. Vielleicht gibt es ein Problem in meinem Code oder etwas Seltsames in der IIS-Konfiguration? Wie kann ich diese Controller-Aktion auf diesen Servern korrekt ausführen?
Dies ist eine einfache Möglichkeit, die Aktion-Methode zu testen (nur die url
Wert direkt für das Routing bekommen müssen):
<div>
<input type="text" id="txt" autofocus />
<button type="button" id="btn">Speak</button>
</div>
<script>
document.getElementById('btn').addEventListener('click', function() {
var text = document.getElementById('txt').value;
var url = window.location.href + '/speak?text=' + encodeURIComponent(text);
var audio = document.createElement('audio');
var canPlayWavFileInAudioElement = audio.canPlayType('audio/wav');
var bgSound = document.createElement('bgsound');
bgSound.src = url;
var canPlayBgSoundElement = bgSound.getAttribute('src');
if (canPlayWavFileInAudioElement) {
// probably Firefox and Chrome
audio.setAttribute('src', url);
audio.setAttribute('autoplay', '');
document.getElementsByTagName('body')[0].appendChild(audio);
} else if (canPlayBgSoundElement) {
// internet explorer
document.getElementsByTagName('body')[0].appendChild(bgSound);
} else {
alert('This browser probably can\'t play a wav file');
}
});
</script>
Haben Sie versucht, eine synchrone Aktionsmethode zu erstellen, ohne sie in eine Aufgabe zu integrieren? Es könnte Probleme mit dem Thread-Pool in diesem Code geben, von dem ASP .NET nichts weiß. –
@DmitryS. Ich bin mir nicht sicher, ob ich einen solchen Test machen kann ... wenn 'synth.Speak' nicht umgebrochen ist, bekomme ich eine Laufzeitausnahme:' InvalidOperationException' (Ein asynchroner Vorgang kann zu diesem Zeitpunkt nicht gestartet werden). Ich mag die Denkweise, aber wenn es ein Thread-Pool-Problem mit ASP.NET wäre, warum würde es auf so vielen anderen Servern funktionieren? – hmqcnoesy
Die neueste Version des Synthesizers hat die 'SpeakAsync()' Methode. Anstatt den Code in 'Task.Run()' einzufügen, können Sie '' SpeakAsync (Text) '' einfach warten. https://msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer.speakasync%28v=vs.110%29.aspx –