Постоянная утечка памяти в SpeechSynthesizer - PullRequest
8 голосов
/ 05 февраля 2010

Я разработал проект, который хотел бы выпустить, в котором используются c #, WPF и объект System.Speech.Synthesizer. Проблема, препятствующая выпуску этого проекта, заключается в том, что всякий раз, когда вызывается SpeakAsync, он оставляет утечку памяти, которая возрастает до возможного сбоя. Я полагаю, что я правильно вымылся после использования этого объекта, но не могу найти лекарство. Я запустил программу через Ants Memory Profiler, и она сообщает, что WAVEHDR и WaveHeader растут с каждым вызовом.

Я создал пример проекта, чтобы попытаться установить причину, но все еще в растерянности. Любая помощь будет оценена.

Проект использует VS2008 и представляет собой проект c # WPF, предназначенный для .NET 3.5 и любого процессора. Вам необходимо вручную добавить ссылку на System.Speech.

Вот код:

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




Я запускаю эту программу в 64-разрядной Windows 7, и она будет запускаться и в конечном итоге останавливаться при попытке создать новый объект SpeechSynthesizer. При запуске в 64-разрядной версии Windows Vista объем памяти возрастет с 34 тыс. До 400 тыс. И будет увеличиваться.

Может ли кто-нибудь увидеть в коде что-либо, что может быть причиной этого, или это проблема самого объекта Речи.

Буду признателен за любую помощь.

Ответы [ 4 ]

5 голосов
/ 17 сентября 2011

Это известная проблема в методе Speak. Структура с именем SPVTEXTFRAG создается и никогда не разрушается.

Подробности здесь: http://connect.microsoft.com/VisualStudio/feedback/details/664196/system-speech-has-a-memory-leak

3 голосов
/ 14 марта 2010

Я могу подтвердить это наблюдение. Я дергал себя за волосы, пытаясь выяснить, где произошла утечка моей программы, и это метод .SPEAK в System.speech

Я преобразовал приложение, использующее объекты речи на основе COM, для использования новой библиотеки System.Speech .Net в .Net 3.5. Звучит как правильный способ перейти к использованию всего управляемого кода в приложении .Net. В приложении внезапно произошла небольшая утечка памяти.

Я разбил это на 2 простых приложения, которые преобразуют «это тест» в WAV-файл из произнесенных слов. Один использует речевые объекты на основе COM, другой использует System.Speech. Я запускал их в течение 24 часов, каждый из которых создавал WAV около 200 000 раз.

Речевые объекты на основе COM: нет утечки памяти. Mem использование приложения достигло максимума в 13 МБ примерно через 40 минут

System.speech: медленная утечка, хорошая и линейная. Работает от около 14 МБ до 45 МБ за 24 часа

2 голосов
/ 26 августа 2010

SendAsync() от Ping также протекает. Решение заключается в том, чтобы сначала отправить отправителя как IDisposable. Поэтому, возможно, здесь также работает следующее.

((IDisposable)spk).Dispose();
0 голосов
/ 15 февраля 2012

Я могу дать вам очень простой ответ на ваш вопрос: Сделайте SpeechSynthesizer статическим !!!

Я совершенно уверен, что это решит вашу проблему.

Также - совет == >> каждый раз, когда вы кодируете, и у вас есть ресурс ... используйте его как статический, и ваша жизнь станет лучше!

...