Новое растровое изображение внутри тела рабочего фона вызывает утечку памяти - PullRequest
0 голосов
/ 20 марта 2019

Я рисую визуализацию для записи данных WaveIn только для целей тестирования, чтобы увидеть, насколько правильными являются данные.Как вы можете видеть, мой механизм:

1) Некоторые потоки WaveIn (не включены) проталкивают эту форму через делегата с аудиобуфером.

2) Фоновый рабочий принимает обновленные аудиоданные,рисовать Bitmap и когда он закончится, он сообщает Progress и этот дескриптор из этого собственного потока формы просто вызывает WM_PAINT для обновления фона PictureBox новым изображением.

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

Проблема в Bitmap .. этот код вызывает утечку памяти,Пожалуйста, помогите мне избежать этой проблемы.

ОБНОВЛЕНИЕ

Да, решение легко, просто избавиться от него .. Я бы получил, конечно, сам, ноУ меня все еще есть более серьезная проблема, и это растровое изображение было только на вершине моего стека, когда оно дошло до стадии, называемой stackoverflow.Но в любом случае это вина ГК .. он должен контролировать такие вещи.Обратный вызов высовывается один раз в секунду. Я никогда не вызывал Dispose для каждого растрового изображения в моих предыдущих проектах.

1 Ответ

1 голос
/ 20 марта 2019

Обновление

«Использование» уничтожит растровое изображение вне его области видимости, но мне все равно нужно его рисовать.

О, дорогой...

Вам все еще нужно Dispose это как-то, как вы воссоздаете его каждый раз ...

Могу я предложить.

soundGraphImage?.Dispose();
soundGraphImage = new Bitmap(graphWidth, graphHeight);

Original

Всегда используйте оператор using для всего, что может его поддержать, придерживайтесь этого правила и (в данном случае) вы, вероятно, будете правы.

В этом отношенииВы должны по крайней мере реализовать using для следующего: -

using(var soundGraphImage = new Bitmap(graphWidth, graphHeight))
{
}

И для других объектов, таких как вызов Graphics, просто чтобы быть последовательным


Дополнительные ресурсы

с использованием оператора (C # Reference)

Предоставляет удобный синтаксис, обеспечивающий правильное использование объектов IDisposable.

Оператор using

Оператор using получает один или несколько ресурсов, выполняет оператор и затем удаляет tРесурс.

Интерфейс IDisposable

Предоставляет механизм освобождения неуправляемых ресурсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...