C#MemoryStream的空内容 [英] C# Empty Contents Of A MemoryStream

查看:98
本文介绍了C#MemoryStream的空内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hello Everyone!

i已经创建了一个可以模拟电钢琴的小应用程序(但它只会播放正弦波)我的应用基于这个文章

现在我正在使用该剧流式传输部分演示。它的作用是将我指定的整个wave文件写入内存,然后使用System.Media.SoundPlayer类播放它。

但问题是每次我点击按钮在表单中播放一个音符,内存使用情况(我正在观看这种情况发生在任务管理器上)增加了几百KB

i认为这是因为我存储了很多数据到内存但我永远不会删除它。所以我的问题是如何清除MemoryStream的内容?

这是我到目前为止:



这是执行的一个单独的主题

Hello Everyone!
i have created a little app that can emulate an electric piano(but it only will play sine waves) i have based my app on this article
now i am using the play to stream part of the demo. what this does is it writes the entire wave file of what ever note i specify into memory and then plays it back using the System.Media.SoundPlayer class.
but the problem is that every time i click the button in the form to play a note, the memory usage (i am watching this happen on task manager) increases by a few hundred KBs
i think this is due to the fact that i am storing a lot of data into memory but i am never deleting it. so my question is how to i clear the contents of a MemoryStream?
here is what i have so far:

this is executed on a separate thread

private void Operation()
{
    //Instalize The MemoryStream(This Is To Store All The Wave Data Into Memory
    MemoryStream stream = new MemoryStream();

    //Construct The Note Sound And Put It Into The Stream
    PlayNote(stream, 180, 5000, false, NoteToPlayFreq, 1, 5000);

    // Jump Back To The Beginning Of The Stream
    stream.Position = 0;

    //Instalize A New Instance Of The Soundplayer Class
    SoundPlayer player = new SoundPlayer(stream);
        
    //Play The Note
    player.PlaySync();

    //This Is Supposed To Clear The Stream But It Dosent
    stream.Dispose();

    //Raise the NoteCompletedEvent event at the end of the program loop
    NoteCompletedEvent();
        
}



现在PlayNote方法是:


now the PlayNote method is this:

public void PlayNote(Stream output, double tempo, short defaultVolume, bool closeUnderlyingStream, float frequency, double length, short volume)
{
    this._tempo = tempo;

    _writer = new WaveWriter16Bit(output, 44100, false, closeUnderlyingStream);

    _defaultVolume = defaultVolume;


    if (volume < 0)
        throw new ArgumentOutOfRangeException("volume", "Volume must be greater than or equal to zero.");

    double samplesPerCycle = _writer.SampleRate / frequency;

    int samplesForNote = (int)(_writer.SampleRate * length * 60 / Tempo);


    Sample16Bit sample = new Sample16Bit();

    for (int currentSample = 0; currentSample < samplesForNote; currentSample++)
    {
        bool endOfStream = true;

        if (_writer.CurrentSample < _writer.NumberOfSamples)
        {
            sample = _writer.Read();
            endOfStream = false;
        }
        else
            sample.LeftChannel = 0;

        // If we're at the end of the note, fade out linearly.
        // This causes two back-to-back notes with the same frequency
        // to have a break between them, rather than being one
        // continuous tone.
        int distanceFromEnd = samplesForNote - currentSample;
        short finalVolume = distanceFromEnd < 1000 ? ((short)(volume * distanceFromEnd / 1000)) : volume;

        double sampleValue = Math.Sin(currentSample / samplesPerCycle * 2 * Math.PI) * finalVolume + sample.LeftChannel;

        if (sampleValue > short.MaxValue)
            sampleValue = short.MaxValue;
        else if (sampleValue < short.MinValue)
            sampleValue = short.MinValue;

        sample.LeftChannel = (short)(sampleValue);

        if (endOfStream == false)
            _writer.CurrentSample--;

        _writer.Write(sample);
    }

    if (_writer != null)
        _writer.Close();
}



i如果我播放了一首长歌(超过几千次按钮点击),那么这个应用的内存使用量将通过屋顶。

所以我做错了什么?

感谢您提前的帮助,

MasterCodeon


i figure that if i played a long song(in excess of a few thousand button clicks) then my memory usage for this app would be through the roof.
so what am i doing wrong?
thanks for your help in advance,
MasterCodeon

推荐答案

我建​​议如果您使用的是您引用的文章中的代码,那么问题就在那里。我浏览了源代码,有几个项目我会清理。前两个是二进制读写器。这些应该在处理班级时专门处理。它们将在垃圾收集例程运行时被处理掉,但是最好在完成后立即关闭流并处理它们。



您还需要记住,dot.net垃圾收集器在处理完后不会立即从内存中删除对象。您不希望GC吸收CPU周期。 GC决定删除对象之前可能需要很短的时间。如果您有兴趣,有很多关于GC如何工作的文章。



希望这给你一个起点。还有一些非常好的产品用于调试内存问题。一个是JetBrains dotMemory。另一个是红门Ants Memory Profiler。我对两者都有过一点经验,而且他们都非常好。微软也有一个免费的,我认为它被称为CLR Profiler或类似的东西。我从来没有使用它,所以我不能说它有多么有用。
I would suggest that if you are using the code from the article you referenced that the issue is in there. I browsed through the source code and there are several items that I would clean up. The first two being the binary reader and writer. These should be specifically disposed when the class is being disposed. They will be disposed of when the garbage collection routine runs, but it is good practice to always close streams and dispose of them as soon as you are finished with them.

You also need to remember that the dot.net Garbage Collector does not neccesarilly remove objects from memory as soon as they are disposed of. You would not want your CPU cycles to be sucked up by the GC. It can take a short time before the GC decides to remove the objects. There are numerous articles on how the GC works if you are interested.

Hopefully this gives you a starting point to look into. There are also some very good products out for debugging memory issues. One is JetBrains dotMemory. Another one is red-gates Ants Memory Profiler. I have had minor experience with both and they are both very good. Microsoft also has a free one, I think it is called CLR Profiler or something like that. I have never used it, so I cannot speak to how useful it is.


通常,至少有两种很好的方法来清理内存流而不浪费大量的CPU和努力。



首先,如果,在某个时刻,你有一个流,并希望得到一个没有任何数据的清晰流,这意味着你没有根本不需要这个可用的流实例。因此,您可以放心地放弃此实例并创建一个新实例,初始化为空数据;而且你可以从头开始添加数据。因此,这是最简单的方法: http://msdn.microsoft .com / zh-CN / library / ad966f9s%28v = vs.110%29.aspx [ ^ ]。



在同一个实例上运行的另一种方式也与流的可能用途有关,就是这样。如果您想要清除流,则意味着您要为其编写新内容。也就是说,您可能只需要忽略以前的内容,而不是删除它。因此,您可以将流回滚到零位置并从此处写入。这是如下:

http://msdn.microsoft.com/en-us/library/system.io.memorystream.position%28v=vs.110%29.aspx [ ^ ],

http:// msdn.microsoft.com/en-us/library/system.io.memorystream.seek%28v=vs.110%29.aspx [ ^ ]。



不合逻辑吗?



-SA
Generally, there are at least two good ways to clean-up a memory stream without wasting much of the CPU and effort.

First of all, if, at some moment, you have a stream and want to get a clear stream without any data, it means that you don't need this available stream instance at all. Therefore, you can safely abandon this instance and create a new one, initialized to empty data; and than you can add data from scratch. Therefore, this is the most trivial way: http://msdn.microsoft.com/en-us/library/ad966f9s%28v=vs.110%29.aspx[^].

Another way operating on the same instance is also related to the possible use of the stream and is this. If you want clear stream, it means that you are going to write new content to it. That is, you may need just to ignore the previous content, not to remove it. Therefore, you can just rewind the stream to zero position and write from this place. This is how:
http://msdn.microsoft.com/en-us/library/system.io.memorystream.position%28v=vs.110%29.aspx[^],
http://msdn.microsoft.com/en-us/library/system.io.memorystream.seek%28v=vs.110%29.aspx[^].

Isn't it logical?

—SA


这篇关于C#MemoryStream的空内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆