Was sind verwaltete / nicht verwaltete Ressourcen

  • VB.NET

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

    Was sind verwaltete / nicht verwaltete Ressourcen

    Hallo Leutz,

    in meinem letzten Thread ging es um Using. Dabei ist auch Code gepostet worden, guckst Du hier, der das Dispose-Pattern beinhaltet. Zunächst wusste ich da nix mit anzufangen, dass hat sich am WE aber geändert. In diesem Kontext tauchen aber immer wieder die Begriffe 'verwaltetete -und nicht verwaltete Ressourcen' auf. Leider konnte ich bisher nirgends eine, mich erleuchtende, Erklärung zu diesen Begriffen finden.

    Ich meine vor längerem gelesen zu haben, das man grob gesprochen, alle Objekte/Klassen, die Dispose bereits implentiert haben als verwaltet ansehen kann und alles andere, zB selbst erstellte Klassen als nicht verwaltet. Aber ich habe irgendwie das Gefühl, dass das die Sache nicht so richtig trifft.

    Könntet ihr mich bitte aufklären? Danke im voraus :)
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!
    Das ist relativ einfach erklärt:
    Verwaltete Ressourcen sind einfach alles, was da im Framework an Typen vorkommt.
    Integer, Byte, DateTime, StringBuilder, Byte-Arrays, DataGridViewRowHeightInfoPushedEventArgs, und so weiter. Auch jede Structure und jede Class, die Du deklarierst sind im Endeffekt verwaltete Ressourcen.

    Aber: Man kann auch unverwaltete Ressourcen verwenden. Ein Beispiel ist die Bitmap-Klasse. Da wird intern ein unverwaltetes Byte-Array verwendet, um die Daten zu speichern. Das kann man sogar herauslesen:

    VB.NET-Quellcode

    1. Dim Bytes As Byte()
    2. Using Bpm As New Bitmap("Pfad")
    3. Dim Bits = Bpm.LockBits(EinPaarParameter)
    4. Dim ByteCount = Bits.Stride * Bits.Height
    5. Bytes = New Byte(ByteCount - 1) {}
    6. System.Runtime.InteropServices.Marshal.Copy(Bits.Scan0, Bytes, 0, ByteCount)
    7. Bipm.UnlockBits(Bits)
    8. End Using

    Beachte Zeile 6. Bits.Scan0 ist ein IntPtr, der auf die Position der unverwalteten Bytes im Arbeitsspeicher zeigt. Mit Marshal.Copy kann man aus unverwaltetem Speicher in verwalteten und umgekehrt kopieren.

    Man braucht relativ oft unverwaltete Ressourcen. Ein Beispiel, auf das man selten achtet, sind Forms.
    Wenn man einen OpenFileDialog öffnet, macht man das üblicherweise so:

    VB.NET-Quellcode

    1. Using Dlg As New OpenFileDialog
    2. If Dlg.ShowDialog() = DialogResult.OK Then
    3. '...
    4. End If
    5. End Using

    Forms (generell Controls) sind stark an Windows gebunden, denn Windows (welches "unverwaltet" ist, wenn man das so sagen will) muss die Controls zeichnen. Da gibt's so einige Verbindungen, die nicht verwalted sind.


    Und das Problem mit den unverwalteten Ressourcen ist, dass sie nicht verwaltet sind. Das heißt, nur Du weißt, wo sie ist (oder halt eben die Klasse, die sie wrappt). Und der GarbageCollector muss wissen, wo sich eine Ressource im Speicher befindet, damit er sie verwerfen kann. Es gibt auch keine richtige Referenzen auf die Ressourcen (im Sinne von: Es gibt keinen Datentyp für unverwaltete Ressourcen).
    Unverwaltete Ressourcen funktionieren also gänzlich anders als verwaltete. Und man muss diese unverwalteten Ressourcen manuell entfernen. Die Bitmap-Klasse macht das, sobald man die Dispose-Methode aufruft. Wenn man das nicht macht und alle Referenzen auf die Bitmap-Instanz entfernt (z.B. die methode, in der die Bitmap lokal deklariert ist, verlässt), dann kann die unverwaltete Ressource nicht mehr gelöscht werden und dann bleibt die im Arbeitsspeicher, bis der Prozess beendet wird.
    Die Ausnahme davon ist, dass der Garbage Collector das Objekt finalisiert, sobald alle Referenzen drauf verschwunden sind. Dabei wird die Finalize-Methode des Objekts aufgerufen und wenn alles richtig implementiert ist (schwierig hinzubekommen, aber bei Bitmaps scheint es zu passen) wird dann die unverwaltete Ressource freigegeben und man hat den Arbeitsspeicher wieder verfügbar.
    Das Problem ist aber: Der Garbage Collector muss das Objekt nicht finalisieren. (Details siehe ericlippert.com/2015/05/18/whe…u-know-is-wrong-part-one/ und ericlippert.com/2015/05/21/whe…u-know-is-wrong-part-two/ )
    Für ihn ist jedes Bitmap-Objekt gleich groß. Einige Bytes dürften das sein: Der Overhead jedes Objekts in .NET (VTable und so Zeugs), ein IntPtr, der auf die unverwalteten Daten zeigt und drei Referenztyp-Felder, die alle Nothing sind. Das sind wenige Bytes. Wahrscheinlich weniger als 60 (die genaue Anzahl hängt von der CLR ab). Der Garbage Collector sieht also nicht, dass da eigentlich noch ein 200MB großes Byte-Array im Arbeitsspeicher liegt, also wird er, wenn der Arbeitsspeicher knapp wird, wahrscheinlich zuerst andere, größere Objekte finalisieren.
    Man darf sich also an der Stelle nicht auf den Garbage Collector verlassen.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Niko Ortner“ ()

    Irgendwo hab ich das mit der Bitmap-Klasse schon mal gelesen. Vor allem, dass man diese immer mit Dispose zerkloppen soll, nun weiß ich warum.

    Das mit den Controls scheint mir auch irgendwie logisch. Aber muss ich mir da wirklich Gedanken machen? Immerhin hat ein Form IDisposable doch implementiert???

    Ein vom GC entsorgtes Object kann ja nicht ein zweites mal entsorgt werden. Da hab ich im Entwicklerbuch Wege gefunden, ne Exeption zu werfen, wenn man da irgendwas vergessen oder falsch gemacht hat.

    Gibt es andererseits Wege, die ich als Anfänger auch begreife, im Zweifelsfall fest zustellen, ob eine Ressource ggf. unverwaltet ist?
    Und kann, wenn man vergisst, unverwaltete Ressourcen freizugeben, schlimmeres als eine OutOfMemoryExeption zu erhalten?
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!

    Storch schrieb:

    Gibt es andererseits Wege, die ich als Anfänger auch begreife, im Zweifelsfall fest zustellen, ob eine Ressource ggf. unverwaltet ist?
    Nicht wirklich, aber du hast es ja selbst programmiert.

    Also unverwaltete Resourcen sind immer iwie was krankhaftes.
    ZB arbeiten viele Apis mit richtigen Pointern, wasses in .net eiglich nicht gibt. Wenn du also eine Klasse hast, die intern mit solch Apis rumfuhrwerkt, etwa Speicher alloziiert, und dabei einen IntPtr erhält, der auf den Speicher zeigt - sowas wäre eine unverwaltete Resource, weil der GC hat keine Ahnung, wasser aufrufen muß, um das, worauf der IntPtr zeigt, freizugeben.

    Aber üblicherweise hast du ühaupt nix damit zu tun.

    ErfinderDesRades schrieb:


    Aber üblicherweise hast du ühaupt nix damit zu tun.


    Das hab ich schon bei mir gedacht.
    In VBA hab ich mir zuweilen mit APi's helfen müsssen aber Net ist mächtig genug, als das ich das vermutlich da nicht brauche.
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!
    Wie ist es mit Objekten zum Fernsteuern von anderen Officeprogrammen, zB Outlook???

    Vermuten würde ich, das diese, zumindest aus der Sicht von VB.Net als nicht verwaltet gelten?

    Edith: Etwas OffTopic aber:
    Wie sollte man es mit dem Schlüsselwort Me handhaben??? Man kann ja alle möglichen Objekte ohne Me ansprechen aber ist es nicht generell besser, immer Me davor zu setzen?
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Storch“ ()

    Storch schrieb:

    Vermuten würde ich, das diese, zumindest aus der Sicht von VB.Net als nicht verwaltet gelten?
    jou - gutes Beispiel

    Edith: Etwas OffTopic aber:
    Wie sollte man es mit dem Schlüsselwort Me handhaben??? Man kann ja alle möglichen Objekte ohne Me ansprechen aber ist es nicht generell besser, immer Me davor zu setzen?
    ich mags nicht, weil ich Code immer kurz haben will.
    Meine nonpublic KlassenVariablen einen Unterstrich als Präfix, und daran erkenne ich eh, dasses Me. ist.
    Annererseits manche Public Member können auch zu Verwechslungen führen, also zb Control-Propertis wie Text, Height, Width - da setze ich schon meist ein Me. davor.

    ErfinderDesRades schrieb:


    ich mags nicht, weil ich Code immer kurz haben will.
    Meine nonpublic KlassenVariablen einen Unterstrich als Präfix, und daran erkenne ich eh, dasses Me. ist.
    Annererseits manche Public Member können auch zu Verwechslungen führen, also zb Control-Propertis wie Text, Height, Width - da setze ich schon meist ein Me. davor.


    Das bestätigt meine Vermutung, das Me nur wirklich wichtig ist, wenn Verwechselungsgefahr besteht. Bei Members hab ich das auch nie angewandt. Ich bin es nur in Formularen von VBA in Bezug auf COntrols gewöhnt. Will es jetzt nicht beschwören (kann es grad nicht testen) aber ich glaube, das man in VBA keine Control ohne Me ansprechen kann.
    GUD Uwe

    :whistling: Wenn ich genau wüsste, was ich nicht weiß, dann wäre mein Wissen vollständig!