首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SpeechSynthesizer中的持续内存泄漏

SpeechSynthesizer中的持续内存泄漏
EN

Stack Overflow用户
提问于 2010-02-05 07:29:11
回答 4查看 2.9K关注 0票数 8

我已经开发了一个项目,我想发布它使用c#,WPF和System.Speech.Synthesizer对象。阻止此项目发布的问题是,每当调用SpeakAsync时,它都会留下内存泄漏,直到最终失败。我相信我在使用这个对象后已经清理干净了,但是找不到解决方法。我已经通过Ants内存分析器运行了这个程序,它报告WAVEHDR和WaveHeader随着每次调用而增长。

我已经创建了一个示例项目,试图找出原因,但仍然不知所措。任何帮助都将不胜感激。

该项目使用VS2008,是一个c# WPF项目,目标是.NET 3.5和任何.NET。您需要手动添加对System.Speech的引用。

代码如下:

代码语言:javascript
运行
复制
<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>

代码语言:javascript
运行
复制
// 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位的Windows7上运行这个程序,当我尝试创建一个新的SpeechSynthesizer对象时,它将运行并最终停止。当在64位Windows Vista上运行时,内存将从34k的起始点增长到目前的大约400k,而且还在不断增长。

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

任何帮助都将不胜感激。

EN

回答 4

Stack Overflow用户

发布于 2011-09-18 03:41:23

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

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

票数 5
EN

Stack Overflow用户

发布于 2010-03-14 20:56:26

我可以证实这一点。我费了九牛二虎之力,试图找出我的程序泄漏在哪里,那就是System.speech中的.SPEAK方法

我已经将一个使用基于COM的Speech对象的应用程序转换为使用.Net 3.5中新的System.Speech .Net库。这听起来像是在.Net应用程序中使用所有管理代码的正确方式。这个应用程序突然出现了一个小的内存泄漏。

我把它分解成两个简单的应用程序,将“这是一个测试”转换为一个WAV文件的口语。一个使用基于COM的speech对象,另一个使用System.Speech。我运行了24小时,每次创建WAV大约200,000次。

基于COM的语音对象:没有内存泄漏。app内存使用率在约40分钟后达到13MB峰值

System.speech:缓慢泄漏,良好且线性。在24小时内从14MB增加到45MB

票数 3
EN

Stack Overflow用户

发布于 2010-08-26 09:26:51

来自PingSendAsync()也会泄露。这里的解决方案是首先将发送者转换为IDisposable。因此,也许下面的方法也适用于这里。

代码语言:javascript
运行
复制
((IDisposable)spk).Dispose();
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2204012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档