首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >后台工作者身体内的新位图导致内存泄漏

后台工作者身体内的新位图导致内存泄漏
EN

Stack Overflow用户
提问于 2019-03-20 06:31:40
回答 1查看 38关注 0票数 -1

我正在为WaveIn记录数据绘制可视化,只是为了测试目的,看看数据有多正确。正如你所看到的,我的机制是:

1)一些WaveIn线程(未包含)通过带有音频缓冲区的委托来插入此表单。

2)后台工作人员获取更新的音频数据,绘制位图,并在完成后报告进度,该本地窗体线程的句柄只需调用WM_PAINT以使用新图片更新PictureBox背景。

代码语言:javascript
复制
object localLock = new object();
Bitmap soundGraphImage;

private void soundGrapher_DoWork(object sender, DoWorkEventArgs e) {
    while(are.WaitOne())
    {
        if (soundGrapher.CancellationPending) {
            e.Cancel = true;
            return;
        }
        if (audioData == null || audioData.Length == 0) continue;
        soundGraphImage = new Bitmap(graphWidth, graphHeight); <----- this one
        Graphics g = Graphics.FromImage(soundGraphImage);
        lock (localLock)
        {
            #region Draw sound
            if (audioParms.nChannels > 1) { Vfw_MessageOut("More than 1 channel"); return; }
            int currentPos = 1;
            int accu = 0;
            int x = 1;
            int maxValue = 0;
            int baseY = soundGraph.Height / 2;

            int bytes = audioParms.wBitsPerSample / 8;
            int portion = (int)Math.Round(1.0 * audioData.Length / bytes / soundGraph.Width, MidpointRounding.ToEven);
            switch (bytes)
            {
                case 1: maxValue = Byte.MaxValue; break;
                case 2: maxValue = Int16.MaxValue; break;
                case 4: maxValue = Int32.MaxValue; break;
            }

            int halfValue = maxValue / 2;
            double coeff = multiPlyer * baseY / halfValue;
            for (int i = 0; i < audioData.Length; i = i + bytes)
            {
                if (currentPos == portion)
                {
                    accu = (int)(accu / portion);
                    g.DrawLine(Pens.White, new Point(x, baseY),
                        new Point(x, baseY - (int)(coeff * accu)));
                    currentPos = 1;
                    i = i - bytes;
                    x++;
                }
                else
                {
                    currentPos++;
                    switch (bytes)
                    {
                        case 1: accu += audioData[i] - halfValue; break;
                        case 2: accu += BitConverter.ToInt16(audioData, i); break;
                        case 4: accu += BitConverter.ToInt32(audioData, i); break;
                    }
                }
            }
            #endregion
        }
            g.Dispose();
            soundGrapher.ReportProgress(0);
    }
}
private void soundGrapher_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {

}
private void soundGrapher_ProgressChanged(object sender, ProgressChangedEventArgs e) {
    soundGraph.Invalidate();
}

问题出在位图中。此代码会导致内存泄漏。请帮我避免这个问题。

更新

是的,解决方案很简单,只需处理它即可。当然,我自己会得到它,但我仍然有一个更大的问题,这个位图在我的堆栈顶部时,它被称为"stackoverflow“的阶段。但不管怎样,都是GC的错。它应该控制这样的事情。回调每秒只触发一次..在我之前的项目中,我从来没有为每个位图调用过Dispose。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-20 07:16:41

更新

“使用”会破坏它的作用域之外的位图,但我仍然需要它来绘制。

哦天哪..。

你仍然需要Dispose它的一些方法,因为你每次都在重新创建它……

我可以建议你。

代码语言:javascript
复制
soundGraphImage?.Dispose();
soundGraphImage = new Bitmap(graphWidth, graphHeight);

原始

总是在任何可以支持它的东西上使用using语句,遵守这个规则,(在这种情况下)你可能是正确的。

在这方面,您至少应该在以下方面实现一个using

代码语言:javascript
复制
using(var soundGraphImage = new Bitmap(graphWidth, graphHeight))
{
}

而在其他对象上,如Graphics调用,只是为了保持一致

其他资源

using statement (C# Reference)

提供了一种方便的语法来确保正确使用IDisposable对象。

The using statement

语句获取一个或多个资源,执行一条语句,然后释放该资源。

IDisposable Interface

提供了一种释放非托管资源的机制。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55250921

复制
相关文章

相似问题

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