Große Bilddatei in DoublebufferedPanel laden OutOfMemory

  • VB.NET

Es gibt 18 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Große Bilddatei in DoublebufferedPanel laden OutOfMemory

    Hallo,

    ich habe ein Bild, welches eine Größe von 69 MB hat.
    Dieses Bild lade ich in ein DoublebufferedPanel.
    Das Bild kann ich in der Anwendung ohne MemoryException 4-mal ca. laden.
    Danach bekomme ich eine Fehlermeldung, dass ich keinen Arbeitsspeicher mehr zur Verfügung habe.
    Wenn ich im Task-Manager schaue, wird mir angezeigt, dass ich noch 3 GB frei habe, was also nicht am Arbeitsspeicher liegen kann.
    Desweiteren wird das Bild komplett aus dem Arbeitsspeicher wieder gelöscht, was man auch im Task-Manager sehen kann.

    Hier die Fehlermeldung:

    Quellcode

    1. System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Unbehandelte Ausnahme</Description><AppDomain>VS.exe</AppDomain><Exception><ExceptionType>System.OutOfMemoryException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Nicht genügend Arbeitsspeicher.</Message><StackTrace> bei System.Drawing.Graphics.CheckErrorStatus(Int32 status)
    2. bei System.Drawing.Graphics.DrawImage(Image image, Rectangle destRect, Int32 srcX, Int32 srcY, Int32 srcWidth, Int32 srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback, IntPtr callbackData)
    3. bei System.Drawing.Graphics.DrawImage(Image image, Rectangle destRect, Int32 srcX, Int32 srcY, Int32 srcWidth, Int32 srcHeight, GraphicsUnit srcUnit)
    4. bei System.Windows.Forms.ControlPaint.DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft)
    5. bei System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle, Color backColor, Point scrollOffset)
    6. bei System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle)
    7. bei System.Windows.Forms.Control.OnPaintBackground(PaintEventArgs pevent)
    8. bei System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
    9. bei System.Windows.Forms.Control.WmPaint(Message&amp;amp; m)
    10. bei System.Windows.Forms.Control.WndProc(Message&amp;amp; m)
    11. bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&amp;amp; m)
    12. bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp;amp; m)
    13. bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)</StackTrace><ExceptionString>System.OutOfMemoryException: Nicht genügend Arbeitsspeicher.
    14. bei System.Drawing.Graphics.CheckErrorStatus(Int32 status)
    15. bei System.Drawing.Graphics.DrawImage(Image image, Rectangle destRect, Int32 srcX, Int32 srcY, Int32 srcWidth, Int32 srcHeight, GraphicsUnit srcUnit, ImageAttributes imageAttrs, DrawImageAbort callback, IntPtr callbackData)
    16. bei System.Drawing.Graphics.DrawImage(Image image, Rectangle destRect, Int32 srcX, Int32 srcY, Int32 srcWidth, Int32 srcHeight, GraphicsUnit srcUnit)
    17. bei System.Windows.Forms.ControlPaint.DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft)
    18. bei System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle, Color backColor, Point scrollOffset)
    19. bei System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle)
    20. bei System.Windows.Forms.Control.OnPaintBackground(PaintEventArgs pevent)
    21. bei System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer)
    22. bei System.Windows.Forms.Control.WmPaint(Message&amp;amp; m)
    23. bei System.Windows.Forms.Control.WndProc(Message&amp;amp; m)
    24. bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&amp;amp; m)
    25. bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp;amp; m)
    26. bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)</ExceptionString></Exception></TraceRecord>
    27. Ein Ausnahmefehler des Typs "System.OutOfMemoryException" ist in System.Drawing.dll aufgetreten.
    28. Nicht genügend Arbeitsspeicher.
    29. Unbehandelte Ausnahme: OutOfMemoryException.


    Ich lade das Bild als Blob-Datei in ein MemoryStream, welchen ich mit Using und Try Catch, Finally verwende.
    Außerdem verschiebe ich das DoublebufferedPanel, sobald das Bild geladen wurde.

    Könnt ihr mir da helfen?

    Danke
    Poste mal bitte den Code, mit welchem Du das Bild in das Panel lädst.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    How to turn OPTION STRICT ON
    Why OPTION STRICT ON
    Wird in einem Backgroundworker geladen:

    Quellcode

    1. Using ms As New MemoryStream(file)
    2. Try
    3. Me.Invoke(Sub() DoubleBufferedPanel1.BackgroundImage = Image.FromStream(ms))
    4. Me.Invoke(Sub() BackgroundImageLayout = ImageLayout.Stretch)
    5. Me.BeginInvoke(New Do_FlushMemory(AddressOf VS.MemoryFlush.FlushMemory))
    6. GC.Collect(1)
    7. Me.Invoke(Sub() DoubleBufferedPanel1.Width = DoubleBufferedPanel1.BackgroundImage.Width)
    8. Me.Invoke(Sub() DoubleBufferedPanel1.Height = DoubleBufferedPanel1.BackgroundImage.Height)
    9. If DoubleBufferedPanel1.Left <> 0 AndAlso DoubleBufferedPanel1.Top <> 0 Then
    10. Me.Invoke(Sub() DoubleBufferedPanel1.Left = 0)
    11. Me.Invoke(Sub() DoubleBufferedPanel1.Top = 0)
    12. End If
    13. Me.Invoke(Sub() DoubleBufferedPanel1.Left = (-DoubleBufferedPanel1.BackgroundImage.Width / 2) + (Panel1.Width / 2))
    14. Me.Invoke(Sub() DoubleBufferedPanel1.Top = (-DoubleBufferedPanel1.BackgroundImage.Height / 2) + (Panel1.Height / 2))
    15. GC.Collect(1)
    16. Catch ex As Exception
    17. Me.Invoke(Sub() MessageBox.Show(ex.InnerException.ToString()))
    18. Finally
    19. file = Nothing
    20. ms.Close()
    21. ms.Dispose()
    22. End Try
    23. End Using
    Mir stellt sich halt die Frage, warum ein Panel und keine PictureBox? Hier verweise ich auf die PictureBoxX.ImageLoaction Property. Die sollte das regeln.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    How to turn OPTION STRICT ON
    Why OPTION STRICT ON
    Sollte doch kein Problem sein, die PictureBox-Klasse zu erweitern und die Property zu setzen.

    VB.NET-Quellcode

    1. Public Class PictureBoxBuffered : Inherits PictureBox
    2. Public Sub New()
    3. MyBase.DoubleBuffered = True
    4. End Sub
    5. End Class


    OK. Muss mich korrigieren. Die DoubleBuffered-Property bei der PictureBox-Klasse ist per Default True so wie es scheint. Ich schau mal, ob ich das reproduzieren kann und melde mich dann wieder.

    Getestet mit einem 108MB-Bild. Hier flackert rein gar nichts.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public Sub New()
    3. InitializeComponent()
    4. Me.PictureBoxBuffered1.ImageLocation = "pic.jpg"
    5. End Sub
    6. End Class
    7. Public Class PictureBoxBuffered : Inherits PictureBox
    8. Private _drag As Boolean = False
    9. Private _dLocation As Point
    10. Public Sub New()
    11. MyBase.DoubleBuffered = True
    12. End Sub
    13. Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
    14. _drag = True
    15. _dLocation = e.Location
    16. End Sub
    17. Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
    18. _drag = False
    19. End Sub
    20. Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
    21. If _drag Then
    22. MyBase.Location = New Point(MyBase.Location.X + e.X - _dLocation.X, MyBase.Location.Y + e.Y - _dLocation.Y)
    23. End If
    24. End Sub
    25. End Class

    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

    How to turn OPTION STRICT ON
    Why OPTION STRICT ON

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „SpaceyX“ ()

    @vivil Du musst nicht jede einzelne Zeile bzw. Property invoken.
    Mach genau ein Invoke auf eine separate Prozedur und handle dort das ganze Handling ab.
    Da kannst Du sogar anständig debuggen.
    Du solltest das alte Bild, wenn ein neues zugewiesen wird, disposen:

    VB.NET-Quellcode

    1. If DoubleBufferedPanel1.BackgroundImage IsNot Nothing Then
    2. DoubleBufferedPanel1.BackgroundImage.Dispose()
    3. End If
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!
    @SpaceyX habe mich vertran, ich benutze eine Pictruebox mit Doublebuffered:

    VB.NET-Quellcode

    1. Public Class DoubleBufferedPanel
    2. Inherits PictureBox
    3. Public Sub New()
    4. 'Me.DoubleBuffered = True
    5. SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    6. SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    7. Me.UpdateStyles()
    8. End Sub
    9. End Class


    @RodFromGermany sobald ich die Form schließe, wird das Hintergrundbild disposed.

    vivil schrieb:

    sobald ich die Form schließe, wird das Hintergrundbild disposed.
    Pro Aufruf / Instanz legst Du genau ein Bild an?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!
    *unnötiges Zitat entfernt*

    Ja genau richtig.
    1 Bild wird in das DoublebufferedPanel geladen, sobald ich aus der Form rausgehe, wird es Disposed.
    Nun kommt manchmal beim verschieben der PictureBox die Meldung. Dort rufe ich DoublebufferedPanel.Refresh() auf.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    @vivil Unterlass bitte das vollständige Zitieren ganzer Posts.
    Was soll dieses Refresh() bewirken?
    Das macht doch das System ganz alleine.
    Nimm das mal raus.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!
    ich täte zunächstmal empfehlen, SpaceyX's Code zu nehmen, ohne jede Veränderung.
    Allen weiteren Code löschen - nix eigenes zufügen, insbesondere bitte nix mit Threading, nix mit GC.Collect, nix mit Refresh, und weiß der Kuckuk.
    Dann sollten imo die erwähnten Fehler nicht mehr auftreten, weil ist eiglich sauber programmiert.

    In einem weiteren Schritt kann man dann sogar auch SpaceyX's PictureBoxBuffered abschaffen, weil Picturebox ist doch von Haus aus DoubleBuffered.
    Uund statt der MouseBlaBla-Overrides kann man ganz normal die entsprechenden MouseBlaBla-Events nehmen, und darin tun, was zu tun ist (ist ja nicht soo viel).
    Auf dem DoublebufferedPanel kann man Linien hinzufügen.
    Es gibt einen Button, der sagt, ob diese Linien sichtbar sein sollen oder nicht.
    ​Desweiteren, kann man Panels, die als kleiner Kasten auf dem DoublebufferedPanel dargetsellt werden, verschieben.
    ​Deshalb wird das .Refresh aufgerufen, damit die Linien auf das Bild gezeichnet werden und die Kästen verschoben werden und die Linien aktualisiert werden.
    @vivil .Refresh() ist da die Holzhammer-Lösung, gut für kleinere GUIs.
    Bei Deinem riesen Bild solltest Du nur die Stellen Deiner PictureBox neu zeichnen, die auch tatsächlich geändert werden sollen (also alte Linie weg, neue Linie hin).
    Dazu hast Du einige .Invalidate(...)-Überladungen, die es Dir gestatten, lediglich kleine Bereiche neu zu zeichnen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!

    vivil schrieb:

    Auf dem DoublebufferedPanel kann man Linien hinzufügen.
    Es gibt einen Button, der sagt, ob diese Linien sichtbar sein sollen oder nicht.
    ​Desweiteren, kann man Panels, die als kleiner Kasten auf dem DoublebufferedPanel dargetsellt werden, verschieben.
    Alles schön und gut, solange es gut gecoded ist.
    Da habich aber Zweifel, und vermute, dein Problem rührt von ungeeignetem Code her - den du uns bislang vorenthälst.
    Wie gesagt: SpaceyX' Code ist soweit ok, und wenn du dich auf den beschränkst, sollte das OutOfMemory behoben sein - und wäre damit gute Ausgangsbasis deiner weiteren Entwicklung.
    @vivil Du musst alle Bereiche hinzufügen, die geändert werden.
    Sieh Dir doch einfach mal die Überladungen von .Invalidate(...) an.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!
    An dem verschieben des Bildes wird es nicht liegen.
    Habe mal den Code von @SpaceyX kopiert und eingefügt, aber dadurch ist das Problem nicht behoben.
    Deshalb denke ich, dass es nur am laden des Bildes liegen kann, bzw. Objekte nicht korrekt freigegeben werden.
    Ein Beispiel:
    Ich klicke in einem DataGrid auf eine Zeile, danach öffnet sich ein neues Control, indem im Backgroundworker die Große Bilddatei geladen wird.
    Sobald das Bild angezeigt wird, klicke ich auf einen Button, um wieder zu meinem vorherigem Datagrid zurückzukommen. Während dieses klicks auf den Button,
    wird das Bild aus dem Doublebufferedpanel Disposed. Diesen Vorgang kann ich immer unterschiedlich lange wiederholen, mal 30-mal, dann auch mal länger, bis
    er eine Fehlermeldung, nicht genügend Arbeitsspeicher wirft.
    Hierzu muss ich noch sagen, dass er nicht an einer bestimmten Stelle im Code anhält, sondern die Meldung 'Die Anwendung befindet sich im Haltemodus' ausgibt.
    Sobald ich dann auf weiter Debuggen klicke, schmiert das Programm ab und ich sehe in der Ausgabe, dass eine Fehlermeldung nicht genügend Arbeitsspeicher geworfen wurde.

    EDIT: Was mir aufgefallen ist, dass Bild an sich ist 69MB groß, die Anwendung lädt, sobald das Bild angezeigt wird, 300MB in den Arbeitsspeicher. Wie kann das sein?

    Hier nochmal das laden des Bildes, welches entweder als Blob aus SQLite geladen wird, oder aus MySQL:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. If _iNetResponse Then
    2. taMapBG = New DataTable
    3. If taMapBG.Columns.Count = 0 Then
    4. taMapBG.Columns.Add("idmap", GetType(String))
    5. taMapBG.Columns.Add("mapname")
    6. taMapBG.Columns.Add("datei", GetType(Byte()))
    7. taMapBG.Columns.Add("groesse")
    8. taMapBG.Columns.Add("speicherdatum")
    9. End If
    10. Dim cnSqlite As SQLiteConnection = New SQLiteConnection()
    11. cnSqlite.ConnectionString = "Data Source=" & VS.main.dbasepfadDatei & ";Password=" & VS.main.dbasepassDatei & ";"
    12. Dim sqlMaps As String = ""
    13. Me.Invoke(Sub() sqlMaps = "SELECT idmap, mapname, datei, groesse, speicherdatum FROM maps WHERE idmap = '" & ddlMap.SelectedValue & "'")
    14. Dim checkMap As New DataTable()
    15. Using query As New SQLiteCommand()
    16. Dim da As New SQLiteDataAdapter
    17. da = New SQLiteDataAdapter(sqlMaps, cnSqlite)
    18. If cnSqlite.State = ConnectionState.Closed Then cnSqlite.Open()
    19. da.Fill(checkMap)
    20. da.Dispose()
    21. query.Dispose()
    22. End Using
    23. cnSqlite.Close()
    24. If checkMap.Rows.Count = 0 Then
    25. Dim sqlMapMySQL As String = ""
    26. Me.Invoke(Sub() sqlMapMySQL = "SELECT idmap, mapname, datei, groesse, speicherdatum FROM maps WHERE idmap = '" & ddlMap.SelectedValue & "'")
    27. Dim cmd As DbCommand = DBO.getDbCommand(sqlMapMySQL, VS.main.cnBGW)
    28. cmd.CommandTimeout = 5000
    29. Dim da As DbDataAdapter
    30. Dim checkMapMySQL As New DataTable()
    31. Try
    32. da = DBO.getDbDataAdapter(cmd)
    33. da.Fill(checkMapMySQL)
    34. Catch ex As Exception
    35. MessageBox.Show(ex.InnerException.ToString())
    36. Finally
    37. cmd.Dispose()
    38. da.Dispose()
    39. End Try
    40. If taMapBG.Rows.Count > 0 Then
    41. Dim newRow As DataRow = taMapBG.NewRow()
    42. newRow("idmap") = checkMapMySQL.Rows(0)("idmap")
    43. newRow("mapname") = checkMapMySQL.Rows(0)("mapname")
    44. newRow("datei") = checkMapMySQL.Rows(0)("datei")
    45. newRow("groesse") = checkMapMySQL.Rows(0)("groesse")
    46. newRow("speicherdatum") = checkMapMySQL.Rows(0)("speicherdatum")
    47. taMapBG.Rows.Add(newRow)
    48. newRow = Nothing
    49. Else
    50. For Each rowMap As DataRow In checkMapMySQL.Rows
    51. Dim newRow As DataRow = taMapBG.NewRow()
    52. newRow("idmap") = rowMap("idmap")
    53. newRow("mapname") = rowMap("mapname")
    54. newRow("datei") = rowMap("datei")
    55. newRow("groesse") = rowMap("groesse")
    56. newRow("speicherdatum") = rowMap("speicherdatum")
    57. taMapBG.Rows.Add(newRow)
    58. newRow = Nothing
    59. Next
    60. End If
    61. checkMapMySQL.Dispose()
    62. checkMapMySQL = New DataTable()
    63. startebgwLoadMapSQLite = True
    64. Else
    65. taMapBG = checkMap
    66. checkMap.Dispose()
    67. checkMap = New DataTable()
    68. End If
    69. Me.BeginInvoke(New Do_FlushMemory(AddressOf VS.MemoryFlush.FlushMemory))
    70. Else
    71. If _idprocesssub <> "" Then
    72. taMapBG = Funktionen.SQLite_DLookupTable(VS.main.cnSQLiteBGW, "M.idmap, M.mapname, M.datei",
    73. "branch_maps AS BM " &
    74. "INNER JOIN maps AS M ON BM.idmap = M.idmap",
    75. "BM.idprocessbranch = " & _idprocessbranch & " AND M.idmap = '" & idmap & "'" &
    76. " AND BM.idprocesssub = '" & _idprocesssub & "'")
    77. If taMapBG.Rows.Count = 0 Then
    78. taMapBG = Funktionen.SQLite_DLookupTable(VS.main.cnSQLiteBGW, "M.idmap, M.mapname, M.datei",
    79. "branch_maps AS BM " &
    80. "INNER JOIN maps AS M ON BM.idmap = M.idmap",
    81. "BM.idprocessbranch = " & _idprocessbranch & " AND M.idmap = '" & idmap & "' AND BM.standardmap = 1")
    82. End If
    83. Else
    84. taMapBG = Funktionen.SQLite_DLookupTable(VS.main.cnSQLiteBGW, "M.idmap, M.mapname, M.datei",
    85. "branch_maps AS BM " &
    86. "INNER JOIN maps AS M ON BM.idmap = M.idmap",
    87. "BM.idprocessbranch = " & _idprocessbranch & " AND M.idmap = '" & idmap & "' AND BM.standardmap = 1")
    88. End If
    89. End If
    90. 'GC.Collect(1)
    91. If taMapBG.Rows.Count > 0 Then
    92. Dim findRow() As DataRow = taMapBG.Select("idmap = '" & idmap & "'")
    93. If findRow.Length > 0 Then
    94. Dim filename As String = findRow(0)("mapname")
    95. Dim file() As Byte = Nothing
    96. If findRow(0)("datei") IsNot DBNull.Value Then file = findRow(0)("datei")
    97. If file IsNot Nothing Then
    98. Using ms As New MemoryStream(file)
    99. Try
    100. Me.Invoke(Sub() DoubleBufferedPanel1.BackgroundImage = Image.FromStream(ms))
    101. Me.Invoke(Sub() BackgroundImageLayout = ImageLayout.Stretch)
    102. Me.Invoke(Sub() DoubleBufferedPanel1.Width = DoubleBufferedPanel1.BackgroundImage.Width)
    103. Me.Invoke(Sub() DoubleBufferedPanel1.Height = DoubleBufferedPanel1.BackgroundImage.Height)
    104. If DoubleBufferedPanel1.Left <> 0 AndAlso DoubleBufferedPanel1.Top <> 0 Then
    105. Me.Invoke(Sub() DoubleBufferedPanel1.Left = 0)
    106. Me.Invoke(Sub() DoubleBufferedPanel1.Top = 0)
    107. End If
    108. Me.Invoke(Sub() DoubleBufferedPanel1.Left = (-DoubleBufferedPanel1.BackgroundImage.Width / 2) + (Panel1.Width / 2))
    109. Me.Invoke(Sub() DoubleBufferedPanel1.Top = (-DoubleBufferedPanel1.BackgroundImage.Height / 2) + (Panel1.Height / 2))
    110. 'GC.Collect(1)
    111. Catch ex As Exception
    112. Me.Invoke(Sub() MessageBox.Show(ex.InnerException.ToString()))
    113. Finally
    114. file = Nothing
    115. ms.Close()
    116. ms.Dispose()
    117. findRow = Nothing
    118. GC.Collect(1)
    119. End Try
    120. End Using
    121. End If
    122. End If
    123. End If



    Hier das freigeben des Objektes, sobald ich auf den Button klicke:

    VB.NET-Quellcode

    1. If ctrlPanel1.BackgroundImage IsNot Nothing Then
    2. ctrlPanel1.BackgroundImage.Dispose()
    3. End If
    4. ctrlPanel1.BackgroundImage = Nothing
    5. objekt_control.taMapBG.Dispose()
    6. objekt_control.taMapBG = New DataTable()

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „vivil“ ()

    vivil schrieb:

    Wie kann das sein?
    Das solltest Du mal in einem separaten kleinen Testprojekt untersuchen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!