Laden...

OutOfMemoryException bei MDI-Anwendung

Erstellt von Wax vor 16 Jahren Letzter Beitrag vor 16 Jahren 8.235 Views
Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren
OutOfMemoryException bei MDI-Anwendung

Hallo Community,

ich habe nun ein Problem, dass ich leider nicht verstehen kann. In meiner MDI-Anwendung ist es problemlos möglich mehrere MDI-Child-Fenster zu erzeugen, wenn die anderen (gleichzeitig geöffneten) MDI-Children minimiert oder verkleinert sind. Sobald aber ein MDI-Child den WindowState-Wert "Maximized" besitzt und ich dann ein neues MDI-Child öffnen möchte, schmiert mir das Programm beim erzeugen des neuen Fensters ab und der Debugger meldet mir eine
OutOfMemoryException {"Fehler beim Erstellen des Fensterhandles."}
an folgender Stelle im Code:


test.Show();

"test" ist mein MDI-Child-Objekt.

Woran liegt dieses Verhalten und wie kann ich es abstellen? Es kann doch nicht wahr sein, dass auf einem Rechner der mir 2GB RAM anzeigt, ein Speicherüberfluss bei solch einer Aktion stattfindet, oder?

MfG
wax

ps.: Es muss dazu gesagt werden, dass die Fenster, welche erzeugt werden nicht irgendwelche endlos-arrays oder so enthalten. Nur ein paar Panels RichTextBoxen. 😁

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Damit man mein Problem auch nachempfinden kann, habe ich mal eine abgespeckte Version meines Progs angehangen. Um den Fehler zu bekommen, einfach nach Start des Projektes mal im Menü "Datei" die beiden Optionen "Anleitung" und "Struktur" nacheinander öffnen ohne ein anderes Fenster zuvor zu schließen. Dann werdet ihr sehen was ich meine. 😁

Also wer Zeit und Lust hat sich das mal anzuschauen, dem danke ich schonmal vielmals.... Man wird erkennen, dass die beiden Form-Klassen "GUIChild_Anleitung" und "GUIChild_Prozess" nicht gerade aufwendig sind. Also ich hoffe jedenfalls, dass ich sie nicht absolut schlecht entworfen habe.

MfG
wax

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Wax,

OutOfMemoryException {"Fehler beim Erstellen des Fensterhandles."}

das heißt nicht, dass dir der Hauptspeicher ausgegangen ist, sondern die freien Fensterhandle. Jedes Control benötigt einen und es gibt m.E. "nur" 64000 Fensterhandle. Vermutlich erzeugst du Controls ohne Dispose zu verwenden, wenn du sie nicht mehr brauchst. Wenn es nicht Fensterhandle sind, dann sind es vielleicht andere Handle, die knapp geworden sind, z.B. für Bitmap, Graphics, Pens, Brushs o.ä. Ebenfalls wegen fehlenden Dispose.

herbivore

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Hallo herbivore,

wenn ich das richtig verstanden habe, könnte ich somit 64000 Controls erstellen?
Also soviel verwende ich nun wirklich nicht. 🙂
Ich verstehe nicht, warum mir die Software nicht abschmiert, wenn ein MDI-Child nicht maximiert ist und dann ein neues erzeugt wird. NUR wenn das aktive Fenster gerade maximiert ist und ich dann ein weiteres erzeuge, tritt der Fehler auf. Hast Du vielleicht ne Ahnung weshalb das sein könnte?

MfG
wax

ps.: Natürlich sind alle anderen Forum-User auch gefragt. 🙂

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Wax,

die 64000 Controls musst du nicht gleichzeitig erzeugen. Das kann auch nach und nach passieren. Und es müssen eben auch nicht unbedingt Controls zu sein, die die Handles verbrauchen. Andere Beispiele habe ich genannt. Ich bin mir sehr sicher, das ein oder mehrere vergessene Dispose die Ursache sind. Schau dir für jede Klasse, die du verwendest und die IDisposable implementiert, an, ob du für alle Objekte, die du erzeugst, auch Dispose aufrufst, wenn du sie nicht mehr brauchst.

herbivore

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Hi herbivore,

ich weiß das sich mein Problem seltsam anhört.
Also, ich bin mir bewusst über die Sache mit dem Dispose und auch, dass ich dieses verwenden muss. Wenn ich aber 2 MDI-Child-GUI´s öffne, kann ich von diesen doch keine Ovjekte wieder freigeben, da sie in Gebrauch sind und von daher eine Referenz auf sie bestehen sollte, oder? Und ich habe es gerade ausprobiert, 10 MDI-Child-GUI´s nacheinander zu erstellen und das ist alles kein Problem. SOLANGE keins der Child-GUI´s vorm öffnen eines anderen nicht den WindowState "Maximized" hatte.
Ich weiß, dass sich das komisch anhört.

Vielleicht liegt das Problem irgendwo in meinem MDI-Parent. Ich hatte mit den Fenstern auch schonmal das Problem, dass wenn ich ein neues MDI-Child erzeugt habe und dieses Fenster von Start an auf "Maximized" gesetzt war, erst ein kleines Fenster im MDI-Parent angezeigt wurde (obwohl man im Icon des Fensters schon sehen konnte, dass es maximiert ist) und erst nach einmal minimieren und dann wieder maximieren wurde es tatsächlich über die ganze Größe des Parents angezeigt. Also irgendwas läuft da nicht sauber.

MfG
wax

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Ich bin manchmal noch nicht ganz fit darin, Fehlermeldungen zu analysieren. Diese hier schmeisst mir der JIT-Debugger entgegen:

System.OutOfMemoryException: Fehler beim Erstellen des Fensterhandles. ---> System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
bei System.Windows.Forms.NativeWindow.WindowClass.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.IntCreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
bei System.Windows.Forms.UnsafeNativeMethods.CreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
bei System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
--- Ende der internen Ausnahmestapelüberwachung ---
bei System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
bei System.Windows.Forms.Control.CreateHandle()
bei System.Windows.Forms.Form.CreateHandle()
bei System.Windows.Forms.Control.get_Handle()
bei System.Windows.Forms.Form.SetVisibleCore(Boolean value)
bei System.Windows.Forms.Control.Show()
bei LectureDiplom.GUIParent.strukturToolStripMenuItem_Click(Object sender, EventArgs e) in C:\Dokumente und Einstellungen\Administrator\Desktop\TestProg\testApp\GUIParent.cs:Zeile 77.
bei System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
bei System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e)
bei System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
bei System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
bei System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
bei System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
bei System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
bei System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea)
bei System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.ScrollableControl.WndProc(Message& m)
bei System.Windows.Forms.ToolStrip.WndProc(Message& m)
bei System.Windows.Forms.ToolStripDropDown.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Dies dürfte wohl alles erklären (nur mir nicht) 😁

MfG
wax

49.485 Beiträge seit 2005
vor 16 Jahren
Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Hmm, naja ich hab ehrlich gesagt kein Plan mehr was ich machen soll. 😁
Also NULL-Verweise finde ich nirgends.

Wenn ich mein Fenster so aufrufe:


GUIChild_Anleitung test = new GUIChild_Anleitung();
test.MdiParent = this;
test.WindowState = FormWindowState.Maximized;
test.Show();

schmiert mir das Programm mit der oben angezeigten Fehlermeldung ab.
Wenn ich aber


GUIChild_Anleitung test = new GUIChild_Anleitung();
test.MdiParent = this;
test.Show();

verwende, ist alles tutti.

Das kanns doch nicht sein, oder?

MfG
wax

G
36 Beiträge seit 2007
vor 16 Jahren

hallo,

ich hatte in einer mdi-anwendung das selbe problem, hier wurde diese exception ausgelöst wenn der cursor in einer datagridview-zeile stand.

ich habe das problem umschieft, indem ich per visiblechanched-event den cursor auf eine ebenfalls vorhandene textbox gesetzt habe.

wo das wirkliche problem liegt würde mich allerdings auch intressieren ....

1.274 Beiträge seit 2005
vor 16 Jahren

Schaut euch mal die Handles und die GDI Objekte anzahl im Taskmanager an.

PS. Angezeigt bekommt man die über Ansicht / Spalten auswählen.

"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Hi LastGentleman,

danke für den Hinweis, ich kannte diese Optionen bisher garnicht. schäm
Also wenn ich mein Programm starte liegt die Handleanzahl immer so bei 280-290 und die GDI-Objektanzahl bei ca. 90. Die GDI-Objektanzahl ändert sich halt bei jedem neu geöffneten MDI-Child entsprechend. Die Handleanzahl bleibt aber immer in diesem gleichen Rahmenbereich von ca. 290. Also ich weiß echt nicht wo da ein Problem sein soll. Doch wie schon gesagt stimmt da irgendwas anderes bestimmt nicht, da das System ja nur abschmiert, wenn ein MDI-Child vor dem öffnen des nächsten den WindowState "Maximized" hat. Also das ist einfach nur verwirrend.

Aber danke an euch, dass ihr euch noch die Mühe gemacht habt zu antworten. 😁

MfG
wax

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Alsoooooo.....

Ich konnte meine Fehlerquelle nun zumindest schonmal eingrenzen. Es handelt sich dabei um eine Methode, die ich beim erzeugen meines neuen MDI-Child-Fensters aufrufe, um ein paar Controls zu zeichnen.
Hier mal der Konstruktor und die von mir definierten Felder meiner MDI-Child-Klasse:


TextBox tempBox;
RichTextBox tempRTBox;      
ArrayList steps = new ArrayList();
ArrayList manuals = new ArrayList();
int lastPosiY;
int lastManualsPosiY;

public GUIChild_Anleitung(Form inMDIParent)
{
    InitializeComponent();
    this.MdiParent = inMDIParent;
    this.addFirstStep();
    this.Show();
}

Der Fehler tritt immer dann auf, wenn ich die Methode "addFirstStep()" in meinem Code lasse. Wenn ich sie entferne funktioniert alles einwandfrei.
Hier mal die Methode addfirstStep():


private void addFirstStep()
{
    // add first step label
    tempBox = new TextBox();
    tempBox.Size = new Size(50, 20);
    tempBox.Location = new Point(35, 45);
    steps.Add(tempBox);
    this.panel_manuals.Controls.Add(tempBox);
                      
    // add first RTBox
    this.tempRTBox = new RichTextBox();
    tempRTBox.Multiline = true;
    tempRTBox.AcceptsTab = true;
    tempRTBox.ScrollBars = RichTextBoxScrollBars.Both;
    int tempWidth = this.panel_manuals.Size.Width;
    tempRTBox.Size = new Size(tempWidth - 170, 100);
    tempRTBox.Location = new Point(152, 3);
    manuals.Add(tempRTBox);
    this.panel_manuals.Controls.Add(tempRTBox);
}

Wenn nun im Konstruktor diese Methode (addfirstStep) ausgeführt wurde und der nächste Aufruf "this.Show()" dran ist, bricht das Programm ab und der Debugger wirft mir den oben genannten Fehler entgegen.

Kann irgendwer erkennen was so "böse" :evil: an meiner addfirstStep-Methode ist?

MfG
wax

ps.: achja und es tritt immer noch erst dann auf, wenn vorm Erzeugen eines neuen Fensters, das alte (bereits aktive) Fenster maximiert ist. Ich kipp gleich vom Stuhl....

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Ok, das Problem liegt in meiner sizeChanged-Ereignismethode:


        private void GUIChild_Anleitung_SizeChanged(object sender, EventArgs e)
        {
            ArrayList controlList = new ArrayList();

            for (int i = 0; i < panel_manuals.Controls.Count; i++)
            {
                if (panel_manuals.Controls[i].GetType().ToString().Equals("System.Windows.Forms.TextBox"))
                {
                    TextBox tempBox = (TextBox)panel_manuals.Controls[i];
                    controlList.Add(tempBox);
                }
                if(panel_manuals.Controls[i].GetType().ToString().Equals("System.Windows.Forms.RichTextBox"))
                {
                    RichTextBox tempBox = (RichTextBox)panel_manuals.Controls[i];
                    tempBox.Size = new Size(panel_manuals.Size.Width - 170, 100);
                    controlList.Add(tempBox);
                }
            }
            this.panel_manuals.Controls.Clear();
            for (int i = 0; i < controlList.Count; i++)
            {
                if (controlList[i].GetType().ToString().Equals("System.Windows.Forms.TextBox"))
                {
                    this.panel_manuals.Controls.Add((TextBox)controlList[i]);
                }
                if (controlList[i].GetType().ToString().Equals("System.Windows.Forms.RichTextBox"))
                {
                    this.panel_manuals.Controls.Add((RichTextBox)controlList[i]);
                }
            }

        } // end of method GUIChild_Anleitung_SizeChanged

Nun muss ich mal schauen wo genau es hängt.

MfG
wax

Wax Themenstarter:in
731 Beiträge seit 2006
vor 16 Jahren

Endlich ist es geschehen. Ich habe einfach den überflüssigen Teil entfernt.


this.panel_manuals.Clear();

for (int i = 0; i < controlList.Count; i++)
{
    if (controlList[i].GetType().ToString().Equals("System.Windows.Forms.TextBox"))
    {
        this.panel_manuals.Controls.Add((TextBox)controlList[i]);
     }
     
    if (controlList[i].GetType().
ToString().Equals "System.Windows.Forms.RichTextBox"))
    {
        this.panel_manuals.Controls.Add((RichTextBox)controlList[i]);
     }
}

Wobei dieser Teil ja nur den alten Panel Inhalt gelöscht und mit Controls aus meiner temporären Control-Liste gefüllt hat. Doch wenn mein Fenster maximiert war, hat das anscheinend gestört. Aus was für einen Grund auch immer. 🤔

MfG
wax