2010-02-04 14 views
8

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.

+0

¿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. –

+0

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

+0

¿Qué ocurre si no creas un nuevo objeto SpeechSynthesizer en cada pase? –

Respuesta

3

Puedo confirmar esta observación. Me estaba tirando de los pelos tratando de descubrir dónde se estaba filtrando mi programa y es el método .SPEAK en System.speech

He convertido una aplicación que utilizaba los objetos de voz basados ​​en COM para usar el nuevo System.Speech Biblioteca .Net en .Net 3.5. Sonó como la forma correcta de avanzar en el uso de todo el código manejado dentro de la aplicación .Net. De repente, la aplicación tuvo una fuga de memoria pequeña.

Rompí esto en 2 aplicaciones simples que convierten "esto es una prueba" en un archivo WAV de palabras habladas. Uno usa los objetos de voz basados ​​en COM, el otro usa System.Speech. Los ejecuté durante 24 horas, cada uno creando el WAV unas 200,000 veces.

Objetos de voz basados ​​en COM: sin pérdida de memoria. El uso de Mem de la aplicación alcanzó su punto máximo en 13 MB después de aproximadamente 40 minutos

System.speech: fuga lenta, agradable y lineal. Rango de aproximadamente 14 MB a 45 MB en 24 horas

+0

¡Gracias! ¡En realidad, tu respuesta es la única correcta! – JXITC

+0

También he encontrado la fuga y ahora la solucioné con su pista. – JXITC

2

SendAsync() del Ping también tiene fugas. La solución allí es convertir al remitente como IDisposable primero. Entonces quizás lo siguiente también funciona aquí.

((IDisposable)spk).Dispose(); 
0

Te puedo dar una respuesta muy simple para su pregunta: Hacer el SpeechSynthesizer estática !!!

Estoy bastante seguro de que esto resolverá su problema.

Además, una sugerencia == >> cada vez que codifica, y usted tiene un recurso ... ¡úselo como estático y su vida sería mejor!

+0

No creo que las instancias sean seguras para subprocesos, es probable que tenga problemas al usar una instancia estática de SpeechSynthesizer en varios subprocesos. – Nariman