SpeechSynthesizer中的常量内存泄漏

时间:2010-02-04 23:29:11

标签: c# wpf memory-leaks text-to-speech

我开发了一个项目,我想发布它使用c#,WPF和System.Speech.Synthesizer对象。阻止此项目发布的问题是,无论何时调用SpeakAsync,都会导致内存泄漏,从而导致最终失败。我相信在使用这个物体后我已经正确清理,但找不到治愈方法。我通过Ants Memory Profiler运行程序,它报告WAVEHDR和WaveHeader随着每次调用而增长。

我已经创建了一个示例项目,试图查明原因,但仍然处于亏损状态。任何帮助将不胜感激。

该项目使用VS2008,是一个针对.NET 3.5和任何CPU的c#WPF项目。您需要手动添加对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();
            }
        }
    }
}




我在Windows 7 64位上运行此程序,它将在尝试创建新的SpeechSynthesizer对象时运行并最终停止。当在Windows Vista 64位上运行时,内存将从34k的起点增长到目前为止大约400k并且不断增长。

任何人都可以在代码中看到可能导致此问题的任何内容,或者这是Speech对象本身的问题。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:5)

这是Speak方法中的一个已知问题。一个名为SPVTEXTFRAG的结构被创建并且永远不会被破坏。

详细信息:http://connect.microsoft.com/VisualStudio/feedback/details/664196/system-speech-has-a-memory-leak

答案 1 :(得分:3)

我可以证实这一观察结果。我正在试着弄清楚我的程序泄漏的位置,这是System.speech中的.SPEAK方法

我已经转换了一个使用基于COM的Speech对象的应用程序,以便在.Net 3.5中使用新的System.Speech .Net库。听起来像是在.Net应用程序中使用所有manged代码的正确方法。该应用突然有一个小内存泄漏。

我将其分解为2个简单的应用程序,将“这是一个测试”转换为口语单词的WAV文件。一个使用基于COM的语音对象,另一个使用System.Speech。我跑了24个小时,每个都创造了大约200,000次WAV。

基于COM的语音对象:没有内存泄漏。应用程序的内存使用率在大约40分钟后达到了13MB

System.speech:缓慢泄漏,漂亮且线性。 24小时内从大约14MB到45MB

答案 2 :(得分:2)

来自SendAsync()

Ping也泄漏了。解决方案是首先将发件人强制转换为IDisposable。所以也许以下内容也适用于此。

((IDisposable)spk).Dispose();

答案 3 :(得分:0)

我可以为您的问题提供一个非常简单的答案: 让SpeechSynthesizer保持静态!!!

我很确定这会解决您的问题。

另外 - 提示==&gt;&gt;每次你编码,你有一个资源......用它作为静态,你的生活会更好!