He desarrollado un proyecto que me gustaría lanzar que utiliza C#, WPF y el objeto System.Speech.Synthesizer. El problema que impide el lanzamiento de este proyecto es que cada vez que se llama a SpeakAsync deja una pérdida de memoria que crece hasta el punto de una falla eventual. Creo que me he limpiado correctamente después de usar este objeto, pero no puedo encontrar una cura. He ejecutado el programa a través del Ants Memory Profiler e informa que WAVEHDR y WaveHeader están creciendo con cada llamada.Pérdida de memoria constante en SpeechSynthesizer
He creado un proyecto de muestra para intentar identificar la causa, pero aún estoy perdido. Cualquier ayuda sería apreciada.
El proyecto usa VS2008 y es un proyecto C# WPF que apunta a .NET 3.5 y cualquier CPU. Necesita agregar manualmente una referencia a System.Speech.
Aquí está el código:
<Window x:Class="SpeechTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<Button Content="Start Speaking" Click="Start_Click" Margin="10" />
<Button Content="Stop Speaking" Click="Stop_Click" Margin="10" />
<Button Content="Exit" Click="Exit_Click" Margin="10"/>
</StackPanel>
</Grid>
// Start of code behind
using System;
using System.Windows;
using System.Speech.Synthesis;
namespace SpeechTest
{
public partial class Window1 : Window
{
// speak setting
private bool speakingOn = false;
private int curLine = 0;
private string [] speakLines = {
"I am wondering",
"Why whenever Speech is called",
"A memory leak occurs",
"If you run this long enough",
"It will eventually crash",
"Any help would be appreciated" };
public Window1()
{
InitializeComponent();
}
private void Start_Click(object sender, RoutedEventArgs e)
{
speakingOn = true;
SpeakLine();
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
speakingOn = false;
}
private void Exit_Click(object sender, RoutedEventArgs e)
{
App.Current.Shutdown();
}
private void SpeakLine()
{
if (speakingOn)
{
// Create our speak object
SpeechSynthesizer spk = new SpeechSynthesizer();
spk.SpeakCompleted += new EventHandler(spk_Completed);
// Speak the line
spk.SpeakAsync(speakLines[curLine]);
}
}
public void spk_Completed(object sender, SpeakCompletedEventArgs e)
{
if (sender is SpeechSynthesizer)
{
// get access to our Speech object
SpeechSynthesizer spk = (SpeechSynthesizer)sender;
// Clean up after speaking (thinking the event handler is causing the memory leak)
spk.SpeakCompleted -= new EventHandler(spk_Completed);
// Dispose the speech object
spk.Dispose();
// bump it
curLine++;
// check validity
if (curLine >= speakLines.Length)
{
// back to the beginning
curLine = 0;
}
// Speak line
SpeakLine();
}
}
}
}
corro este programa en Windows 7 64 bits y se ejecutará y eventualmente detener al intentar crear un nuevo objeto SpeechSynthesizer. Cuando se ejecuta en Windows Vista de 64 bits, la memoria crecerá desde un punto de partida de 34k hasta aproximadamente 400k y seguirá creciendo.
¿Alguien puede ver algo en el código que podría estar causando esto, o es un problema con el objeto Speech en sí mismo.
Cualquier ayuda sería apreciada.
¿Estás seguro de que sigue subiendo continuamente? la memoria continuará subiendo en .net, hasta que el GC llegue y limpie las cosas. a menos que suba continuamente y NUNCA baje, entonces no me preocuparía. –
Sí, cuando ejecuto esto en Windows 7 eventualmente se detendrá cuando intente crear un nuevo objeto SpeechSynthesizer. Después de que el programa se detiene, ir al panel de control e intentar probar Text-To-Speech resultará con el mismo. Ya no hablará hasta que la máquina se reinicie. – DudeFX
¿Qué ocurre si no creas un nuevo objeto SpeechSynthesizer en cada pase? –