OutOfMemoryException für eine vb.net-Anwendung

8

In einer meiner VB.Net-Anwendungen erhalte ich Fehler beim Ausführen der Anwendung. Dieser Fehler kommt nicht immer. Daher kann ich den Fehler auch nicht reproduzieren. Keine exakte Sequenz auch um den Fehler zu reproduzieren.

  

Stack: System.OutOfMemoryException: Nicht genügend Arbeitsspeicher.   bei System.Drawing.Graphics.FromHdcInternal (IntPtr hdc)   bei System.Windows.Forms.ToolStrip.OnPaint (PaintEventArgs e)   bei System.Windows.Forms.Control.PaintWithErrorHandling (PaintEventArgs e, Int16-Ebene, Boolean deposeEventArgs)   bei System.Windows.Forms.Control.WmPaint (Nachricht & amp; m)   bei System.Windows.Forms.Control.WndProc (Nachricht & amp; m)   bei System.Windows.Forms.ScrollableControl.WndProc (Nachricht & amp; m)   bei System.Windows.Forms.ToolStrip.WndProc (Nachricht & amp; m)   bei System.Windows.Forms.StatusStrip.WndProc (Nachricht & amp; m)   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage (Nachricht & amp; m)   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc (Nachricht & amp; m)   bei System.Windows.Forms.NativeWindow.Callback (IntPtr hWnd, Int32-Nachricht, IntPtr wparam, IntPtr lparam)

Fehlerbeschreibung:

  

MyApplication_UnhandledException

Nach diesem Fehler bekomme ich eine Nachricht,

  

Nicht genügend Speicher zum Erstellen einer Bitmap. Schließen Sie eine oder mehrere Anwendungen, um die Verfügbarkeit zu erhöhen.

Wenn ich den Speicherverbrauch der Anwendung überprüft habe, war es nicht so hoch. Dieser Fehler wird nicht wiederholt angezeigt. So, wie ich diesen Fehler beheben kann. Wie kann es gelöst werden? Ich überprüfte die Ausführung meiner Anwendung mit dem .Net-Speicherprofiler und dem Redgate-Speicherprofiler.

Unten ist ein Screenshot der Menge der nicht verwalteten Speicherbelegung. Ich weiß nicht genau, ob diese Werte hoch sind.

UPDATE:

Ich habe den Fehler erneut.Checked die GDI-Objekte und es war 9998.So der Fehler wegen hoher GDI-Objekte.Now Frage ist, wie zu lösen.Then dann habe ich GDIView und überprüft. Mit diesem Tool habe ich Stift-2954 Pinsel-5918 Schriftart-90 Bitmap-13 usw. GDI total-9998 Also, was Thesen Stift und Pinsel sind? In meinem Code habe ich keinen Pinsel oder Stift verwendet. (Ich habe den Code für 'Stift' und 'Pinsel' gesucht, aber habe keinen bekommen.) Also bitte hilf mir dabei.

    
IT researcher 18.07.2013, 14:19
quelle

1 Antwort

8

Wechseln Sie in Ihrem Task-Manager in das Anzeigen -Menü, um auszuwählen, welche Spalten auf der Registerkarte Prozesse angezeigt werden sollen. Wählen Sie, dass die Spalte GDI-Objekte angezeigt werden soll. Ich bin mir ziemlich sicher, dass Sie sehen werden, dass die gesamten GDI-Objekte für Ihren Prozess 10000 erreichen, was das Maximum für jeden Prozess darstellt.

Es ist keine Frage, wie viel physischer Speicher verwendet wird. In diesem Sinne ist die Fehlermeldung sehr schlecht und irreführend. Das Problem ist, dass Sie keine GDI-Handles mehr haben. Jeder Prozess unter Windows ist auf eine maximale Anzahl von GDI-Handles beschränkt, die sie erstellen können. Das Limit liegt derzeit bei 10000 Handles pro Prozess.

Der Grund, warum ich davon ausgehe, dass Ihr Problem die GDI-Handles sind, liegt daran, dass die Ausnahme ausgelöst wird, wenn Sie versuchen, beim Malen des Steuerelements eine neue Bitmap zu erstellen. Eine Bitmap ist ein GDI-Objekt. Beim Erstellen einer Bitmap wird ein GDI-Handle für diese Bitmap verwendet. Daher ist das wahrscheinlich die Ursache.

Da der Fehler im Standardsteuerelement ToolStrip auftritt, ist es wahrscheinlich kein Fehler mit dem ToolStrip selbst. Es ist viel wahrscheinlicher, dass Sie an anderer Stelle in Ihrem Programm alle GDI-Handles verwenden. Wenn das Steuerelement versucht, sich selbst zu zeichnen, schlägt es fehl, weil keine Handles mehr vorhanden sind.

Jedes Mal, wenn Sie GDI-Objekte wie Stifte und Bitmaps erstellen, müssen Sie sicherstellen, dass Sie diese Objekte entsorgen. Alle GDI-Klassen, die GDI-Handles erwerben, implementieren die IDisposable -Schnittstelle. Wenn die Objekte entfernt werden, löschen sie automatisch ihre Griffe an diesem Punkt. Aber, wenn Sie die Objekte nie entsorgen, werden die Handles nie gelöscht und Ihre GDI-Objektanzahl wird einfach weiter wachsen.

Um jedes Objekt IDisposable zu entfernen, können Sie einfach die Methode Dispose aufrufen, wenn Sie mit dem Objekt fertig sind, zum Beispiel:

%Vor%

Wenn Sie können, ist es sogar noch besser, die Variablen für IDisposable -Objekte mit einem Using -Block wie folgt zu deklarieren:

%Vor%

Mit dem Using -Block wird die Methode Dispose automatisch für Sie aufgerufen, so dass Sie sie nicht explizit aufrufen müssen. Der Grund dafür, dass der Using -Block besser ist als der Aufruf von Dispose selbst, liegt darin, dass die Using -Methode immer noch automatisch aufgerufen wird, wenn innerhalb des Dispose -Blocks eine Ausnahme ausgelöst wird. Wenn Sie es explizit selbst aufrufen, ohne einen Using -Block, ist es einfacher, jeden Ort zu verpassen, den Sie anrufen müssen.

Um den Problembereich in Ihrem Code zu finden, führen Sie Ihr Programm im Debugger aus und gehen Sie durch Ihren Code. Lassen Sie den Task-Manager geöffnet und zeigen Sie die Spalte GDI-Objekte an, während Sie den Code schrittweise bearbeiten. Sehen Sie sich die GDI-Objekte -Spalte im Task-Manager an und Sie werden feststellen, dass die Anzahl zunimmt, wenn neue GDI-Objekte erstellt werden. Es sollte ziemlich einfach sein, mit dieser Methode zu sehen, wo das Problem liegt.

    
Steven Doggart 18.07.2013, 14:28
quelle