2010-02-04 7 views
8

저는 C#, WPF 및 System.Speech.Synthesizer 개체를 사용하여 출시 할 프로젝트를 개발했습니다. 이 프로젝트의 출시를 방해하는 문제는 SpeakAsync가 호출 될 때마다 최종 실패 지점까지 증가하는 메모리 누수가 남습니다. 나는이 객체를 사용한 후에 제대로 정리했다고 믿지만 치료법을 찾을 수 없습니다. Ants Memory Profiler를 통해 프로그램을 실행했으며 각 호출마다 WAVEHDR 및 WaveHeader가 증가하고 있다고보고합니다.SpeechSynthesizer의 상수 메모리 누수

나는 그 원인을 찾아 내기 위해 샘플 프로젝트를 만들었지 만 여전히 손실에 처해있다. 어떤 도움을 주시면 감사하겠습니다.

프로젝트는 VS2008을 사용하며 .NET 3.5 및 모든 CPU를 대상으로하는 C# WPF 프로젝트입니다. System.Speech에 대한 참조를 수동으로 추가해야합니다. 나는 윈도우 7 64 비트를이 프로그램을 실행하고 실행하고 새로운 SpeechSynthesizer 객체를 생성 할 때 결국 중단됩니다

<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(); 
      } 
     } 
    } 
} 




: 여기

는 코드입니다. Windows Vista 64 비트에서 실행될 때 메모리는 34k의 시작 지점에서부터 약 400k까지 성장할 수 있습니다.

누군가 코드에서이 문제를 일으킬 수있는 내용을 볼 수 있습니까? 아니면 이것이 Speech 개체 자체의 문제입니까?

도움을 주시면 감사하겠습니다.

+0

계속 하시겠습니까? 메모리가. NET에서 계속 올라갈 때까지 GC를 통해 온다 물건을 청소. 그것이 계속 올라가고 절대로 내려 오지 않는다면, 나는 그것에 대해 걱정하지 않을 것입니다. –

+0

예, Windows 7에서 실행하면 SpeechSynthesizer 개체를 새로 만들 때 중지됩니다. 프로그램이 중단 된 후 제어판으로 이동하여 텍스트 음성 변환을 테스트하려고 시도하면 동일한 결과가 발생합니다. 기계가 다시 시작될 때까지 더 이상 말을하지 않습니다. – DudeFX

+0

각 패스에서 새 SpeechSynthesizer 개체를 만들지 않으면 어떻게됩니까? –

답변

3

이 관찰을 확인할 수 있습니다. 나는 내 프로그램이 유출되고있는 곳을 알아 내려고 노력했다. System.speech에서 .SPEAK 메서드가 사용되었다.

나는 COM 기반의 Speech 개체를 사용하여 새로운 System.Speech를 사용하는 응용 프로그램을 변환했다. .NET 3.5 .Net 라이브러리 .Net 앱에서 모든 코드를 사용하여 앞으로 나아갈 수있는 올바른 방법이라고 생각됩니다. 응용 프로그램이 갑자기 작은 메모리 누수가 발생했습니다.

"이 테스트는"음성 단어의 WAV 파일로 변환하는 2 개의 간단한 앱으로 분류했습니다. 하나는 COM 기반 음성 개체를 사용하고 다른 하나는 System.Speech를 사용합니다. 24 시간 동안 WAV를 만들었습니다. 각각 약 20 만 번 WAV를 만들었습니다.

COM 기반 음성 개체 : mem 누출 없음. 약 40 분 후에 13MB의 메모리 사용량이 최고로 높아졌습니다.

System.speech : 느린 누수, 양호하고 선형입니다. 24 시간 이내에 약 14MB에서 45MB로

+0

감사합니다. 사실 당신의 대답이 유일한 것입니다! – JXITC

+0

나는 또한 누수를 발견하고 지금 당신의 힌트로 해결했습니다. – JXITC

2

SendAsync()Ping에서 누수가 발생합니다. 해결책은 발신자를 IDisposable으로 먼저 캐스팅하는 것입니다. 그럼 어쩌면 다음과 같은 것도 여기에서 작동합니다.

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

나는 귀하의 질문에 당신에게 정말 간단한 대답을 줄 수 있습니다 SpeechSynthesizer 정적 확인!

본인의 문제가 해결 될 것으로 확신합니다.

팁 - 당신이 코딩 할 때마다 == >> 리소스가 있습니다 ... 정적으로 사용하면 인생이 더 좋아질 것입니다!

+0

인스턴스가 스레드로부터 안전하다고 생각하지 않습니다. 여러 스레드에서 정적 SpeechSynthesizer 인스턴스를 사용하면 문제가 발생합니다. – Nariman