Hintergrundinformationen über User Handles

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von roepke.

    Hintergrundinformationen über User Handles

    Hallo zusammen,

    hat irgendjemand genaueres Hintergrundwissen über Windows User Handles oder kann mir eine gute Quelle nenne, in der ich mich darüber ausgiebig informieren kann?

    Konkret: Windows kann ohne Manipulation der Registry ja nur 10k User Handles pro Anwendung verwalten. Sind es mehr passieren mitunter merkwürde Dinge in der Anwendung.
    Meine Anwendung ist mittlerweile immens groß und es werden Unmengen von User Handles erstellt auf die ich scheinbar keinen direkten Einfluss ausüben kann, außer in dem ich Code umformuliere.
    So erstellt z.B. ein

    VB.NET-Quellcode

    1. If (MyForm.GetType = frm_Main.GetType) then
    2. End If


    jede Mange User Handles und lässt diese nach dem End If bestehen, anstatt diese wieder zu entfernen.

    Ein

    VB.NET-Quellcode

    1. If CBool((InStr(MyForm, "frm_Main") then
    2. End If


    hingegen öffnet keine oder so gut wie keine User Handles.
    Dies gilt zumindest, wenn ein GetType auf Forms angewendet wird.
    Ich würde gerne mehr über User Handles wissen und die Mechanismen verstehen und so deren Anzahl nach Möglichkeit drastisch reduzieren.
    Im WWW bin ich aber bisher nicht aussagkräftig fündig geworden.
    Evtl. benutze ich auch die falschen Suchbegriffe.
    Vielen Dank für Tipps und Infos jedweder Art zu diesem Thema.
    Ich möchte zum einen verhindern, dass meine Anwendung unbemerkt die max. zulässige Anzahl von User Handels sprengt.
    Das ist mir schon passiert und dann passieren merkwürdige Dinge.
    Und zum anderen möchte ich gerne verstehen was sich hinter den User Handles wirklich verbirgt.
    Rufe ich z.B. ein AddHandler auf vergrößert dies die Anzahl der User Handles nicht.
    Eine For..Loop Schleife hingegen sehr wohl.
    Durch Veränderungen im Code (wie Eingangs bzgl. GetType erwähnt) konnte ich schon einiges an User Handles einsparen.

    roepke schrieb:

    Ich möchte zum einen verhindern, dass meine Anwendung unbemerkt die max. zulässige Anzahl von User Handels sprengt.
    Durch geeignete Programmierung kann man das vermeiden.
    Wenn man mehr als 10k Handles in Anspruch nimmt liegt wohl ein Design-Fehler der Anwendung vor.
    Oft (soweit man hier von "oft" reden kann) liegts daran, dass zuviele Controls erstellt werden.

    roepke schrieb:

    Rufe ich z.B. ein AddHandler auf vergrößert dies die Anzahl der User Handles nicht.
    Korrekt.

    roepke schrieb:

    Eine For..Loop Schleife hingegen sehr wohl.
    Ne. Eine For-Schleife erzeugt keine Handles.

    Ok, also das was du gerade meinst sind keine allgemeinen Handles, sonder User Objects. Diese sind pro Anwendung im Standard auf 10'000 Limitiert. Du kannst dir die Anzahl auch im Taskmanager anzeigen lassen. Diese User-Objects sind im Grunde einfach nur Zeiger auf native Controls, die du bei Windows direkt angefordert hast. Dazu zählen z.B. Form, Brush, Pen, Button, Checkbox .... also so gut wie alles im System.Windows.Forms Namespace. Weil diese Controls alle native Zeiger beinhalten, sind diese natürlich auch alles mit dem IDisposable Interface implementiert. Wenn du also z.B. einen Brush nach dem Zeichnen nicht mehr brauchst, dann rufst du natürlich myBrush.Dispose() auf, um das native Handle wieder frei zu geben und die User Object Anzahl zu verringern, oder packst den Brush im Idealfall direkt in ein ​using ()-Block.

    Wenn du eine Form Disposed, dann ruft diese intern direkt für alle Controls die auf ihr liegen auch Dispose auf, um alles sauber wieder frei zu geben.

    Dialoge: Instanziierung von Forms und Aufruf von Dialogen

    Ich schätze also einfach mal, dass in deiner bisherigen Programmierung das IDisposable Interface nicht richtig beachtet worden ist und dadurch die ganzen Controls mit den nativen Handles (User Objects) einfach liegen bleiben und sich aufstauen. Wenn du alles sauber wieder freigibst, sollte die Grenze von 10'000 eigentlich groß genug sein.

    roepke schrieb:

    Dies gilt zumindest, wenn ein GetType auf Forms angewendet wird.
    Das soll man auch keinesfalls tun.
    Das ist so ein vb6-Ranz, bei dem intern eine Form-Instanz erzeugt wird und zunächstmal unsichtbar bleibt.
    Wenn du sowas drinne hast, hast du tatsächlich möglicherweise ein Resourcen-Leak.
    Ein anderes Resourcen-Leak entsteht, wenn du Forms mit .ShowDialog anzeigst, das Form nach dem Schliessen aber nicht disposest.

    Aber da werden dir weitergehende Informationen über Window-Handles im allgemeinen auch nicht helfen.
    Was du wissen musst ist bereits gesagt:
    • Disposable Objekte disposen, wenn sie nicht mehr gebraucht werden
    • kein GetType auf Forms anwenden
    • keine Forms programmieren mit trillionen an Controls


    Was du ebenfalls brauchst - aber ist ein anneres Thema - ist Visual Studio - Empfohlene Einstellungen
    Diese Codezeile aus post#1

    roepke schrieb:

    VB.NET-Quellcode

    1. If CBool((InStr(MyForm, "frm_Main") then
    ist höchst fehlerhaft (es sei denn, MyForm wäre ein String, was ich stark bezweifel).
    Das zeigt, dass du noch garnet in der .Net-Programmierung angekommen bist, und Datentypen noch nicht sicher identifizieren kannst.
    Zum andern wirst du hunderte solcher "kleinen" Fehler im Programm haben, die eigentlich garnet kompilieren dürften.
    Die meisten dieser Fehler wirken sich nicht aus, aber einige sicherlich doch, und führen auf sehr unauffällige Weise zu einem Programmverhalten, was anners ist als vorgesehen.
    Vielen Dank an Euch.
    Ohne mich jetzt rausreden zu wollen: ich habe das Projekt von einem Kollegen übernommen, der dafür bekannt ist Quick and Dirty mittels Spaghetti-Code ratz-fatz irgendwelche Ergebnisse abzugeben, der aber auch regelmäßig die notwendige Sorgfalt vermissen lässt.
    Ich selbst komme aus dem Bereich VHDL und C und wundere mich schon geraume Zeit über die vielen Schweineigeleinen die sich in Visual Basic ohne Compilerwarnungen machen lassen. Mit den obigen Informationen lichtet sich einiges.
    Die Sache mit Option Strict On hatte ich schon länger aufgeräumt, aber das Abschalten der Visual Basic Namespaces öffnet ganz neue Horizonte. Denn siehe da, die bis dato „Fehler freie“ Anwendung strotz nur so vor Problemen!
    Das wird ein langer Weg und ein hartes Stück Arbeit und ich nehme an, dass ich bestimmt noch die ein- oder andere Frage haben werde, wie ich Dinge besser machen kann.
    Im Moment schaffe ich mir erst mal RegExp() drauf um Dinge wie InStr() zu beseitigen.