2009-05-21 19 views
0

Das ist interessant. Wir haben den letzten Tag damit verbracht, ein Problem mit dem folgenden (älteren) Code zu patchen, der weiterhin seine Prozessgröße erhöht. Dies geschieht in Visual Studio 2003.Warum verursacht dies einen Speicherverlust?

Wir haben ein Formular, auf dem wir ein Bild (aus MemoryStream) und etwas Text und eine Schaltfläche anzeigen. Nichts Außergewöhnliches. Sieht ungefähr so ​​aus:

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 

Diese Form wird häufig geschlossen und geöffnet. Bei jedem erneuten Öffnen erhöht sich die Prozessspeicherauslastung um etwa 5 MB. Wenn das Formular geschlossen wird, fällt es nicht auf seine vorherige Verwendung zurück. Die Ressourcen bleiben für das nicht referenzierte Formular reserviert. Das Formular wird wie folgt wiedergegeben:

 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) 

Die Steuerung später aus der Form entfernt wird, nach dem Schließen:

Me.Controls.Clear() 

Jetzt. Wir haben sehr viele Dinge ausprobiert. Wir haben festgestellt, dass Disposing nichts tut, und tatsächlich berührt die Schnittstelle IDisposable den Speicher nicht. Wenn wir nicht jedes Mal ein neues CJ5Form_PTOperatorAcknowledgement-Formular erstellen, wächst die Prozessgröße NICHT. Wenn Sie jedoch ein neues Bild in dieses Formular laden, wird die Prozessgröße immer größer.

Irgendwelche Vorschläge würden geschätzt.

Antwort

2

Sie müssen Ihr WebClient-Objekt und alle anderen verwalteten nicht verwalteten Ressourcen, die nicht mehr benötigt werden, löschen.


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

Ein noch besserer Weg, um Code, der eine ‚Verwendung‘ Anweisung zu verwenden wäre:


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

Für weitere Informationen wenden Sie sich bitte nach ‚entsorgen‘ und ‚IDisposable‘ -Muster Implementierung auf Google und Stackoverflow .

Ein letzter Hinweis: Verwenden Sie, wenn möglich, keinen Speicherstream. Laden Sie das Bild direkt aus der Datei, es sei denn, Sie müssen es im RAM behalten.

bearbeiten

Wenn ich Ihren Code richtig verstehen vielleicht so etwas wie dies funktionieren würde:


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

„Verwenden“ Anweisung nicht bis Visual Studio 2005. Dispo hinzugefügt wurde, ist nicht das Problem hier . Wir haben jede Variante der Objektentsorgung ohne Erfolg ausprobiert. Wir haben auch versucht, eine lokale Kopie der Datei zu speichern, anstatt einen Speicherstream zu verwenden. – Daniel

+0

Verwenden Sie COM-Objekte? Möglicherweise müssen Sie System.Runtime.InteropServices.Marshal.ReleaseComObject auf Ihren COM-Objekten aufrufen? – user79755

+0

Keine COM-Objekte beteiligt. Das EINZIGE, was bisher funktioniert hat, ist die Wiederverwendung desselben Formularobjekts, anstatt jedes Mal ein neues Objekt zu instanziieren. Das wäre eine Lösung, wenn wir nicht jedes Mal ein neues Bild in das Formular laden müssten (was die Prozessgröße immer noch vergrößert). Es ist, als ob der Garbage Collector nicht erkennt, dass das alte Objekt nicht mehr referenziert wird.Wir können sogar irgendwelche funktionalen Dinge auf dem Formular weglassen und die Prozessgröße wächst weiter. – Daniel

0

Ich weiß nicht, warum speziell das ist undicht, aber ich kann empfehlen, dass Sie mit der .NET Memory Profiler betrachten. Wenn Sie Ihre Anwendung damit ausführen, erhalten Sie eine sehr gute Vorstellung davon, welche Objekte nicht entsorgt werden, und helfen Ihnen bei der Fehlerbehebung. Es hat eine kostenlose Testversion, aber es ist den Kauf wert.

Verwandte Themen