简体   繁体   English

SpeechSynthesizer中的常量内存泄漏

[英]Constant Memory Leak in SpeechSynthesizer

I have developed a project which I would like to release which uses c#, WPF and the System.Speech.Synthesizer object. 我开发了一个项目,我想发布它使用c#,WPF和System.Speech.Synthesizer对象。 The issue preventing the release of this project is that whenever SpeakAsync is called it leaves a memory leak that grows to the point of eventual failure. 阻止此项目发布的问题是,无论何时调用SpeakAsync,都会导致内存泄漏,从而导致最终失败。 I believe I have cleaned up properly after using this object, but cannot find a cure. 我相信在使用这个物体后我已经正确清理,但找不到治愈方法。 I have run the program through Ants Memory Profiler and it reports that WAVEHDR and WaveHeader is growing with each call. 我通过Ants Memory Profiler运行程序,它报告WAVEHDR和WaveHeader随着每次调用而增长。

I have created a sample project to try to pinpoint the cause, but am still at a loss. 我已经创建了一个示例项目来试图查明原因,但我仍然处于亏损状态。 Any help would be appreciated. 任何帮助,将不胜感激。

The project uses VS2008 and is ac# WPF project that targets .NET 3.5 and Any CPU. 该项目使用VS2008,是针对.NET 3.5和Any CPU的ac#WPF项目。 You need to manually add a reference to System.Speech. 您需要手动添加对System.Speech的引用。

Here is the Code: 这是代码:

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




I run this program on Windows 7 64 bit and it will run and eventually halt when attempting to create a new SpeechSynthesizer object. 我在Windows 7 64位上运行此程序,它将运行并最终在尝试创建新的SpeechSynthesizer对象时停止。 When run on Windows Vista 64 bit the memory will grow from a starting point of 34k to so far about 400k and growing. 当在Windows Vista 64位上运行时,内存将从34k的起点增长到目前为止大约400k并且在不断增长。

Can anyone see anything in the code that might be causing this, or is this an issue with the Speech object itself. 任何人都可以在代码中看到可能导致此问题的任何内容,或者这是Speech对象本身的问题。

Any help would be appreciated. 任何帮助,将不胜感激。

This is a know issue in the Speak method. 这是Speak方法中的一个已知问题。 A structure called SPVTEXTFRAG gets created and never destroyed. 一个名为SPVTEXTFRAG的结构被创建并且永远不会被破坏。

Details here : http://connect.microsoft.com/VisualStudio/feedback/details/664196/system-speech-has-a-memory-leak 详情请访问: http//connect.microsoft.com/VisualStudio/feedback/details/664196/system-speech-has-a-memory-leak

I can confirm this observation. 我可以证实这一观察结果。 I was pulling my hair out trying fo figure out where my program was leaking and it is the .SPEAK method in System.speech 我正在试着弄清楚我的程序泄漏的位置,这是System.speech中的.SPEAK方法

I have converted an app that used the COM-based Speech objects to use the new System.Speech .Net library in .Net 3.5. 我已经转换了一个使用基于COM的Speech对象的应用程序来使用.Net 3.5中的新System.Speech .Net库。 Sounded like the right way to move forward to using all manged code within the .Net app. 听起来像是在.Net应用程序中使用所有manged代码的正确方法。 The app suddenly had a small mem leak. 该应用突然有一个小内存泄漏。

I broke this down into 2 simple apps that convert "this is a test" to a WAV file of spoken words. 我将其分解为2个简单的应用程序,将“这是一个测试”转换为口语单词的WAV文件。 One uses the COM-based speech objects, the other uses System.Speech. 一个使用基于COM的语音对象,另一个使用System.Speech。 I ran them for 24 hours, each creating the WAV about 200,000 times. 我跑了24小时,每次创造WAV大约200,000次。

COM based speech objects: no mem leak. 基于COM的语音对象:没有内存泄漏。 Mem usage of app peaked at 13MB after about 40 minutes 大约40分钟后,应用程序的内存使用率达到了13MB

System.speech: slow leak, nice and linear. System.speech:缓慢泄漏,漂亮且线性。 Ran from about 14MB to 45MB in 24 hours 24小时内从大约14MB到45MB

SendAsync() from the Ping also leaks. 来自Ping SendAsync()也泄漏。 The solution there is to cast the sender as IDisposable first. 解决方案是首先将发件人转换为IDisposable So maybe the following also works here. 所以也许以下也适用于此。

((IDisposable)spk).Dispose();

I can give you a really simple answer for your question: Make the SpeechSynthesizer static!!! 我可以为你的问题提供一个非常简单的答案: 让SpeechSynthesizer静态!

I am quite sure that this will solve your issue. 我很确定这会解决你的问题。

Also - a tip ==>> every time you code, and you have a resource... use it as static and your life would be better! 此外 - 每次编码时都会提示== >>,并且您拥有资源......将其用作静态,您的生活会更好!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM