Laden...

"Error creating window handle" beim neu Erstellen von Controls, obwohl alte mit Dispose freigegeben

Erstellt von steffen_dec vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.411 Views
S
steffen_dec Themenstarter:in
322 Beiträge seit 2007
vor 12 Jahren
"Error creating window handle" beim neu Erstellen von Controls, obwohl alte mit Dispose freigegeben

Hallo Leute,

ich habe eine Anwendung mit einer Plugin-Schnittstelle.
Jedes Plugin besitzt eine Datenklasse und ein User-Control.

In der Datenklasse ist das jeweilige User-Control als Member-Variable definiert.
Über eine Property der Datenklasse greift die Anwendung auf das User-Control zu. Das User-Control wird beim ersten Zugriff erst angelegt.
Beispiel:


private ctlMyControl m_formular = null;
public UserControl OptionsForm
        {
            get
            {
                if (m_formular == null || m_formular.IsDisposed)
                {
                    m_formular = new ctlMyControl(this);
                    m_formular.Dock = DockStyle.Fill;
                }
                return m_formular;
            }
        }

Dieses Usercontrol wird später in einer Groupbox der Anwendung angezeigt sobald dieses vom Bediener benötigt wird.

Wenn dieses dann nicht mehr benötigt wird, wird über die Datenklasse dann das Control disposed:


public void DisposeOptionsForm()
        {
            if (m_formular != null && !m_formular.IsDisposed)
            {
                m_formular.Dispose();
                m_formular = null;
            }
        }

In den Plugins werden keine GDI-Objekte verwendet.

Wenn man nun sehr viele solche verschiedene UserControls öffnet und wieder schließt, stürzt die Anwendung mit der Exception "Error creating window handle" ab.

So wie ich es verstehe gehen die Window-Handles zur Neige. Nur verstehe ich nicht warum nach dem Dispose diese nicht freigegeben werden?

Habe ich noch etwas übersehen?

Vielen Dank!
Gruß
Steffen

I
279 Beiträge seit 2008
vor 12 Jahren

Hi,

das Control kann nicht freigegeben werden wenn es irgendwo noch Referenziert ist (z.b. von deiner UI verwendet wird).

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo iced-t89,

ein Windows-Forms-Control besteht aus zwei Teilen, dem der Win32-Basis (unmanaged) und dem .NET Wrapper (managed). Der Aufruf von Dispose zerstört die Win32-Basis. Nach dem Dispose bleibt also eine entkernte Hülle zurück. Diese wird zwar in der Tat nicht verworfen, wenn sie weiterhin auf eine Weise referenziert wird, dass der GC nicht ausschließen kann, dass das Objekt weiterhin benutzt wird. Der Handle ist aber eine Eigenschaft des Win32 Kerns, der ja schon verworfen ist. Für die Anzahl der Handles ist es also irrelevant, wie viele Hüllen noch umhergeistern.

Hallo steffen_dec,

warum der Fehler bei dir auftritt, weiß ich nicht. Die Handles sollten eigentlich freigegeben werden. Versuche mal den Fehler in einer kontrollierten Umgebung nachzustellen. Damit meine ich ein minimales Test-Projekt, wie in [Tutorial] Vertrackte Fehler durch Vergleich von echtem Projekt mit minimalem Testprojekt finden beschrieben, das zudem die Erzeugung und Zerstörung von wirklich allen Controls mitzählt. Zweimal Achtung: zum einen musst du zwischen Dispose und Finalizer unterscheiden (s.o.) und zum anderen arbeitet der GC in einem extra Thread; du musst also die Zugriffe auf die Zählvariablen synchronisieren (z.B. volatile/lock).

BTW:

Wenn dieses dann nicht mehr benötigt wird, wird über die Datenklasse dann das Control disposed:

Falsche Richtung! Die Datenklasse sollte sich nicht um die Controls kümmern, nicht darauf zugreifen, sie nicht mal kennen. Das ist auch nie nötig. Der Zugriff sollte immer in die andere Richtung erfolgen. Das GUI kennt die Datenobjekte und kann darauf zugreifen. Wenn die Datenobjekte dem GUI etwas mitteilen möchten, können sie dafür eigene Events definieren, die das GUI abonniert.

herbivore