Speicher auf mobilen Gerät mit WinCE freigeben



  • Ich schreibe gerade ein Programm in C# für einen BarcodeScanner mit WindowsCE.
    Darin werden sehr oft Forms geöffnet und wieder geschlossen.
    Ich hab schon heraus gefunden, dass man anstatt this.Close(); den Befehl this.Dispose();
    benutzen muss damit die Fenster wirklich geschlossen werden und nicht nur in den
    Hintergrund verlagert werden.

    Jetzt die eigentliche Frage:
    Nach dem schliessen eines Forms wird der Speicher nicht mehr freigegeben, was später
    zum Absturz führt. Gibt es eine Möglichkeit
    den GarbageCollector effektiv anzustossen oder eine ander Möglichkeit den Speicher
    wieder frei zu bekommen? Mit GC.Collect(); passiert nicht viel.



  • hältst du vielleicht irgendwo noch eine Referenz auf das Formular?
    Das ist meist der Grund für solche Speicherlöcher. Eine Methode, die man zuvor an ein Event eingehängt hat zum Beispiel. Wenn man dann erwartet, dass der Speicher nach Form.Dispos() freigegeben wird, wird man schnell enttäuscht.



  • Zur Zeit hab ich noch eine Klasse die "Globale" Daten enthält und die ist hat in jeder Klasse eine "Referenz" oder "Instanz".

    Gute Frage: Wenn ich eine Instanz der Klasse einem Konstruktor übergebe, geht das in c# als Referenz oder wird da eine Kopie übergeben??

    Kann es daran liegen, das diese Klasse überall vorhanden ist?
    Würde es was bringen wenn ich diese zur Singlton mach?

    Ich hab auch festgestellt das unter WindowsCE Objekte in Fenstern nicht mit dem Schliessen diesem auch gelöscht werden. Mir ist das mit Streams aufgefallen, dass man immer mit Stream.Close(); arbeiten muss und Stream = null; nichts bringt. Was aber bei Objekten die kein Close entahlten. Reicht da eventuell Obj = null;? (siehe Frage(n) oben)

    Weiss vielleicht jemand eine Lektüre zu meinem Problem?
    Danke.



  • Die Klasse wird als Referenz übergeben. Im Gegensatz zu Java gibts bei C# Werte- und Referenztypen, obwohl sie vollkommen ojektorientiert ist. Wertetypen sind z.b. die eingebauten numerischen Datentypen und bool, Enum und Structs. Der große Rest wie Klassen(bzw. deren Objekte) werden als Referenzen übergeben.

    Stream.Close() hat aber eher den Hintergrund das der Stream geschlossen werden muss um Datenverlust zu verhindern, deshalb Close(). Dabei wird vor allen auch der darunterliegende native Stream geschlossen, es müssen ja IO Funktionen vom OS angesprochen werden. Bei Dispose() wird der Stream bei Default aber glaube ich auch geschlossen. Dieses "Dispose-Pattern" findet sich ja in vielen Framework Klassen, gerade weil kein manuelles Speicherfreigeben möglich ist, und C# bietet dafür ja auch das using-Statement an, das genau den Aufruf von Dispose garantiert. Bei Stream = null wird ja der darunterliegende unmanaged Stream nicht geschlossen und die nicht .Net Resourcen werden nicht freigegeben. Es wird nur die Referenz entfernt, das Objekt existiert ja noch im Speicher und da kann der GC recht wenig mit anfangen.

    Alle Klassen die unmanaged Resourcen benutzen sollten auch das Dispose Pattern implementieren, sonst sind sie schlecht designed, denn unmanaged Resourcen werden immer im Dispose freigegeben, die managed Resourcen erledigt dann der GC falls nicht noch Referenzen darauf existieren. Bei reinen managed Code reicht es somit das Objekt auf null zu setzen, dass der GC es "demnächst" berücksichtig.



  • Danke für die Erklärung.

    Die Klasse wird als Referenz übergeben. Im Gegensatz zu Java gibts bei C# Werte- und Referenztypen [...]

    Warum gibts dann das ref zum übergeben, wenn eh immer eine Referenz übergeben wird?

    Was ist managed code und was ist unmanaged code?
    Kann damit leider nichts anfangen.
    Da werd ich mir noch so richtig gedanken über meinen code machen müssen 😉



  • Pandur schrieb:

    Danke für die Erklärung.

    Die Klasse wird als Referenz übergeben. Im Gegensatz zu Java gibts bei C# Werte- und Referenztypen [...]

    Warum gibts dann das ref zum übergeben, wenn eh immer eine Referenz übergeben wird?

    Was ist managed code und was ist unmanaged code?
    Kann damit leider nichts anfangen.
    Da werd ich mir noch so richtig gedanken über meinen code machen müssen 😉

    ref verwendest du bei Wertetypen wie z.b. Integern um mit denen als Referenz zu arbeiten:

    static void ChangeValue(ref int val) {
        val = 10;
    }
    
    stativ void Main() {
        int i = 5;
        Console.WriteLine(i);
        ChangeValue(ref i);
        Console.WriteLine(i);
    }
    

    Als Ausgabe erhälst du erst 5 und dann 10. Blödes Beispiel, aber denke wird verständlich.

    Managed Code bedeutet das der Code von der Runtime verwaltet wird. Im Fall von .Net regelt die Runtime das ganze Exception Handling, den GC usw.. Java ist vom Prinzip her auch managed Code.

    Unmanaged Code sind die "alten"(nicht .Net) Codes. Sprich so ziemlich alles was es sonst noch so an Bibliotheken usw. gibt. Momentan überwiegt der Anteil unmanaged Code den Anteil managed Code an Applikationen noch gewaltig. Microsoft hat viel getan dass man unmanaged Code auch gut in managed Code benutzen kann. Wenn du aber unmanaged Code bzw. Resourcen verwendest, dann musst du dafür sorgen das du die selber freigibst, weil die liegen außerhalb vom Wirkungsbereich der Runtime.

    In meinem Artikel zu .Net gehe ich auch kurz auf die Aufgaben der Runtime ein, vielleicht hilft das ein klein wenig weiter.


Anmelden zum Antworten