Почему это вызывает утечку памяти? - PullRequest
0 голосов
/ 21 мая 2009

Это интересно. Мы провели последний день, пытаясь исправить проблему с помощью следующего (устаревшего) кода, который продолжает увеличивать размер своего процесса. Это делается в Visual Studio 2003.

У нас есть форма, на которой мы отображаем изображение (из MemoryStream), а также текст и кнопку. Ничего фантастического. Выглядит примерно так:

  Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
    MyBase.OnLoad(e)
    Try
      m_lblWarning.Visible = False

      m_grpTitle.Text = m_StationInterface.ProcessToolTitle
      m_lblMessage.Text = m_StationInterface.ProcessToolMessage

      Dim objImage As MemoryStream
      Dim objwebClient As WebClient
      Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)

      objwebClient = New WebClient

      objImage = New MemoryStream(objwebClient.DownloadData(sURL))
      m_imgLiftingEye.Image = Image.FromStream(objImage)

      m_txtAcknowledge.Focus()
    Catch ex As Exception
      '*** This handles a picture that cannot be found without erroring'
      m_lblWarning.Visible = True
    End Try
  End Sub

Эта форма часто закрывается и открывается. Каждый раз, когда он снова открывается, использование памяти процесса увеличивается примерно на 5 Мб. Когда форма закрыта, она не возвращается к своему предыдущему использованию. Ресурсы остаются выделенными для формы без ссылок. Форма отображается так:

      m_CJ5Form_PTOperatorAcknowlegement = New CJ5Form_PTOperatorAcknowlegement
      m_CJ5Form_PTOperatorAcknowlegement.stationInterface = m_StationInterface
      m_CJ5Form_PTOperatorAcknowlegement.Dock = DockStyle.Fill
      Me.Text = " Acknowledge Quality Alert"

      '*** Set the size of the form'
      Me.Location = New Point(30, 30)
      Me.Size = New Size(800, 700)

      Me.Controls.Add(m_CJ5Form_PTOperatorAcknowlegement)

Элемент управления позже удаляется из формы после закрытия:

Me.Controls.Clear()

Теперь. Мы пробовали очень много вещей. Мы обнаружили, что Disposing ничего не делает, и, действительно, интерфейс IDisposable фактически не касается памяти. Если мы не создаем новую форму CJ5Form_PTOperatorAcknowledgement каждый раз, размер процесса НЕ увеличивается. Но загрузка нового изображения в эту форму по-прежнему приводит к постоянному увеличению размера процесса.

Любые предложения будут оценены.

Ответы [ 2 ]

2 голосов
/ 21 мая 2009

Вы должны утилизировать свой объект WebClient и любые другие управляемые неуправляемые ресурсы, которые больше не нужны.


objImage = New MemoryStream(objwebClient.DownloadData(sURL))
objwebClient.Dispose() ' add call to dispose

Еще лучший способ написания кода - использовать оператор using:


using objwebClient as WebClient = New WebClient      
objImage = New MemoryStream(objwebClient.DownloadData(sURL))      
end using

Для получения дополнительной информации, пожалуйста, найдите реализацию шаблонов 'Dispose' и 'IDisposable' в google и stackoverflow.

Последний совет: не используйте поток памяти, если это возможно. Загружайте изображение напрямую из файла, если вам не нужно хранить его в оперативной памяти.

Редактировать

Если я правильно понимаю ваш код, возможно, что-то вроде этого будет работать:


Dim objImage As MemoryStream      
Dim objwebClient As WebClient      
Dim sURL As String = Trim(m_StationInterface.ProcessToolPicLocation)      
using objwebClient as WebClient = New WebClient      
  using objImage as MemoryStream = New MemoryStream(objwebClient.DownloadData(sURL))      
    m_imgLiftingEye.Image = Image.FromStream(objImage)
  end using
end using
0 голосов
/ 21 мая 2009

Я не знаю, почему именно это происходит, но я могу порекомендовать вам взглянуть на использование .NET Memory Profiler . Если вы запустите свое приложение, используя это, оно даст вам очень хорошее представление о том, какие объекты не удаляются, и поможет выяснить причину. У него бесплатная пробная версия, но она того стоит.

...