У меня есть приложение ASP.NET asp.net, которое имеет действие контроллера, которое берет строку в качестве входных данных и отправляет ответ wav-файла синтезированной речи. Вот упрощенный пример:System.Speech.Synthesis зависает с высоким процессором в 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;
}
Применение (и этот метод действий, в частности) работает нормально в среде сервера на 2008 серверов R2, 2012 серверов (не R2), и мой 8,1 Dev ПК. Он также отлично работает на стандартной виртуальной машине Azure 2012 R2. Однако, когда я развертываю его на трех серверах R2 R2 R2 (его возможном постоянном доме), метод действий никогда не вызывает ответа HTTP - процесс IIS Worker неограниченно увеличивает один из ядер процессора. В телезрителе событий ничего нет, и при просмотре сервера с Procmon ничего не выпрыгивает. Я подключил процесс с удаленной отладкой, и synth.Speak(text)
никогда не возвращается. Когда выполняется вызов synth.Speak(text)
, я сразу вижу процесс runaway w3wp.exe в диспетчере задач сервера.
Моей первой была склонности верить какой-то процесс вмешивается в синтезе речи в целом на серверах, но для Windows Рассказчик работает правильно, и простое консольное приложение, как это работает правильно:
static void Main(string[] args)
{
var synth = new System.Speech.Synthesis.SpeechSynthesizer();
synth.Speak("hello");
}
Так, очевидно, Я не могу винить синтез речи сервера в целом. Так может быть, в моем коде есть проблема или что-то странное в конфигурации IIS? Как я могу заставить это действие контроллера работать на этих серверах?
Это простой способ проверить метод действия (просто должно получить право url
значения для маршрутизации):
<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>
Вы пытались сделать это синхронным методом действий, не обернув его задачей? В этом коде могут возникнуть проблемы с пулом потоков, о котором ASP.NET не знает. –
@DmitryS. Я не уверен, что могу сделать такой тест, как эта работа ... Если 'synth.Speak' не завернут, я получаю исключение во время выполнения:' InvalidOperationException' (асинхронная операция не может быть запущена в это время). Мне нравится линия мышления, но если это проблема пула потоков с ASP.NET, почему она будет работать на многих других серверах? – hmqcnoesy
Последняя версия синтезатора имеет метод 'SpeakAsync()'. Вместо того, чтобы обертывать код в 'Task.Run()', вы можете просто «ждать SpeakAsync (text)». https://msdn.microsoft.com/en-us/library/system.speech.synthesis.speechsynthesizer.speakasync%28v=vs.110%29.aspx –