errox Geschrieben 14. September 2010 Teilen Geschrieben 14. September 2010 Hallo. Gibt es in C# .NET (auch .NET CF) eine andere möglichkeit außer den GarbageCollector um Arbeitsspeicher freizugeben? Zur zeit sieht mein Code so aus: private void btnSave_Click(object sender, EventArgs e) { DataBase.Unit unit = new Unit(); ..... Working Code.... // Ram freigeben unit = null GC.Collect(); } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 14. September 2010 Teilen Geschrieben 14. September 2010 Wozu? Außerdem sollte man den Garbage Collector nicht selber aufrufen bzw. erreicht man dazu keinerlei Vorteil. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Gateway_man Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Außerdem sollte man den Garbage Collector nicht selber aufrufen bzw. erreicht man dazu keinerlei Vorteil. In manchen Situationen ist es durchaus erforderlich. Beispielsweise wenn man notgedrungen mit der Speicheradresse eines Objektes arbeiten muss und das jeweilige Objekte dann dafür Pinnen sollte, da ansonsten die Möglichkeit besteht, das der Garbage Collector das Objekt an eine andere Stelle im Speicher verschiebt und somit die Adresse ungültig wird. Man könnte jetzt sagen. Sowas macht/braucht man im .NET nicht. Aber die Tatsache das solche Funktionen existieren, legt nahe, dass es dafür sehrwohl einige dafür vorgesehene Situationen gibt.(Zumindest aus Sicht der Entwickler des Frameworks). lg Gateway Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
.NETter Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Hallo, man sollte hier GC.Collect() nicht mit einem direkten Befehl an den GC verwechseln. Mit GC.Collect() kann man den GC ausschließlich darum "bitten" es zu tun. Ob er es tut liegt nicht in unserer Hand! Ausserdem sollte man am Objekt vor einem initialen Aufruf des GC ein .Dispose() am Objekt ausführen um das Objekt zu "zerstören" ein = null entfernt lediglich den Verweis auf das Objekt, welches aber erstmal im Speicher existent bleibt bis der GC entschieden hat ob es vernichtet wird. So sollte der GC das nicht mehr benötigte Objekt auch direkt aus dem Speicher entsorgen. Viele Grüße, Thomas Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
errox Geschrieben 15. September 2010 Autor Teilen Geschrieben 15. September 2010 Okey dann drück ich mich mal anders aus: Ich hab diverse Klassen (selbst geschrieben) und diverse normale Variablen (int, string) Und weil ich auf einem mobilgerät schaff und nur 2 MB freien Arbeitsspeicher hab, möchte ich jede Variable die ich nicht mehr Brauch freigeben. Das muss doch irgentwie gehen oder? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
.NETter Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Naja gut eine einzelne Variable vom Typ int zu entsorgen finde ich etwas überzogen. Die fressen kaum Speicher. Wenn Du Deinen Klassen beibringen möchtest sich zerstören zu können (.Dispose()), kannst Du das Interface IDisposable nutzen. Die Methode des Interface implementieren und fertig. In etwa so: public class MyClass[COLOR="Red"] : IDisposable[/COLOR] { int alter; string name; [COLOR="red"] #region IDisposable Member public void Dispose() { this.Dispose(); } #endregion[/COLOR] } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Und weil ich auf einem mobilgerät schaff und nur 2 MB freien Arbeitsspeicher hab, möchte ich jede Variable die ich nicht mehr Brauch freigeben.Freier Speicher ist nutzloser Speicher. Hast du einen konkreten Problemfall, oder ist das mehr ein "Bauchgefühl"? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Die Methode des Interface implementieren und fertig. Die Implementierung sollte dann aber doch aus etwas mehr als einem Selbstaufruf bestehen. Und der Nutzen, vor allem, wenn keine Unmanaged-Ressourcen freizugeben sind, ist wohl begrenzt. Implementing a Dispose Method Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
errox Geschrieben 15. September 2010 Autor Teilen Geschrieben 15. September 2010 Freier Speicher ist nutzloser Speicher. Hast du einen konkreten Problemfall, oder ist das mehr ein "Bauchgefühl"? Leider ein konkretes Problem. Auf meinem Handy läuft TouchFlo, Windows Media Player, etc. Der Media Player startet sich leider jedes mal Neu, wenn ich eine Form öffne. Desshalb brauch ich jedes kb an RAM. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Ausserdem sollte man am Objekt vor einem initialen Aufruf des GC ein .Dispose() am Objekt ausführen um das Objekt zu "zerstören" ein = null entfernt lediglich den Verweis auf das Objekt, welches aber erstmal im Speicher existent bleibt bis der GC entschieden hat ob es vernichtet wird. Nein sollte man nicht. Denn das einzige was du damit bewirkst ist nutzloser Arbeitsaufwand des GCs. Sobald keine Refrenz mehr auf ein Objekt existiert kann der Speicher potenziell vom GC freigegeben werden und das ist alles was zählt. Wann der GCs das tut entscheidet er selber, spätestens tut er es aber dann wenn der Speicher auch benötigt wird. Das heißt wenn man solche Sachen macht um Resourcen "freizugeben", verbraucht man in Wirklichkeit bei ca.99% der Fälle unötig Resourcen durch unötige durchläufe des GCs statt etwas positives zu erreichen. Aus dem selben Grund sind auch so tolle Tools die ungenutzen Arbeitsspeicher "freigeben" total sinnlos weil das Betriebssystem das sowieso macht wenn er benötigt wird. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
errox Geschrieben 15. September 2010 Autor Teilen Geschrieben 15. September 2010 ..... Das heißt wenn man solche Sachen macht um Resourcen "freizugeben", verbraucht man in Wirklichkeit bei ca.99% der Fälle unötig Resourcen durch unötige durchläufe des GCs statt etwas positives zu erreichen. ..... Das heisst du findest meine Idee Schwachsinnig den Arbeitsspeicher von mir aus in meinem Programm freizugeben oder wie soll ich das sehen? Ich hab halt folgendes Problem: Ich arbeite mit C# .NET 3.5 (Compact Framework, ganz Wichtig) auf einem Gerät mit Gerade mal 51.11 MB RAM (Windows Mobile 6.5). Wenn Paralell Telefoniert wird, das Bluetooth an ist, der Media Player ebenfalls und andere Applikationen habe ich Gerade mal 2 MB Arbeitsspeicher zu verfügung. Mein größtes Problem ist: läuft meine Applikation flüssig und es ruft mich jemand an, werden alle Applikationen (von WM selbst) beendet damit das Telefonat entgegen genommen werden kann. Beispiel: Meine Applikation läuft, Windows Media Player. Es ruft mich jemand an. Ich merk das vorerst garnicht. Zuerst wird Entweder Windows Media Player oder meine Appliaktion beendet. Und ich möchte einfach dass meine Applikation weniger Arbeitsspeicher verbraucht damit sie erst garnicht beendet werden muss. Es ist nicht nur ein "Bauchgefühl" dass ich den Arbeitsspeicher freigebe, sondern eher ein muss damit die Applikation läuft. Das muss doch irgentwie gehen dass ich den RAM einer Variable oder einer Instanz einer Klasse freigeben kann ohne alles auf NULL zu setzen und dann den GC aufzurufen. By the Way: Was genau hat eig die Dispose() Methode auf sich? Im enddefekt (laut MSDN) ruft meine Dispose Methode in meiner Klasse die Dipose() Methoden der Instanzen auf: public void Dispose() { Dispose(true); // Use SupressFinalize in case a subclass // of this type implements a finalizer. GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { // If you need thread safety, use a lock around these // operations, as well as in your methods that use the resource. if (!_disposed) { if (disposing) { if (_resource != null) [B]_resource.Dispose();[/B] Console.WriteLine("Object disposed."); } // Indicate that the instance has been disposed. _resource = null; _disposed = true; } } Was genau passiert dann in dieser Instanz? Ich versteh das nicht so ganz. Alle rufen einfach nur Dispose auf und es Passiert nichts? Was mach ich wenn ich ein Int Array mit 1000 werten habe? Da gibt es kein Dispose. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Und ich möchte einfach dass meine Applikation weniger Arbeitsspeicher verbraucht damit sie erst garnicht beendet werden muss. Es ist nicht nur ein "Bauchgefühl" dass ich den Arbeitsspeicher freigebe, sondern eher ein muss damit die Applikation läuft.Deine Vorgehensweise beruht aber auf der Vermutung, dass der GC nicht sowieso schon alles unternimmt, um Speicher zu sparen, bevor der Speicher zu Ende geht. Das muss doch irgentwie gehen dass ich den RAM einer Variable oder einer Instanz einer Klasse freigeben kann ohne alles auf NULL zu setzen und dann den GC aufzurufen.Hast du wirklich geprüft, ob dieses GC.Collect überhaupt einen positiven Effekt auf dein Programm hat? Du solltest vielleicht eher dein Programm so ändern, dass es von vornherein weniger Speicher reserviert. Alle rufen einfach nur Dispose auf und es Passiert nichts? Was mach ich wenn ich ein Int Array mit 1000 werten habe? Da gibt es kein Dispose.Dispose ist dann sinnvoll, wenn du unmanaged-Ressourcen verwaltest. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Hier gibts 2 Artikel die einen guten Überblick geben: An Overview of the .Net Compact Framework Garbage Collector - Steven Pratschner's .Net CF WebLog - Site Home - MSDN Blogs Simon Hart: Memory management on Windows Mobile <= 6.1 Mit 2MB Arbeitsspeicher bist du anscheinend sowieso schon an der Grenze wo das System versucht aufzuräumen so das sich zwangsläufig etwas beenden muss. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Rekon1602 Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Hallo Ich hatte schon manchmal die Situation, dass ein GC.Collect() mir Vorteile eingebracht hat. Bei mir wars verbunden mit einem StreamReader und einem StreamWriter. Wollte schnell hintereinander schreiben und lesen und schreiben und........ Ein GC.Collect() alleine hat bei mir aber nicht gereicht. Es musste noch zusätzlich ein GC.WaitforCollectionFinished() (oder so ähnlich heißt die funktion). Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Was meinst du mit "schneller schreiben und lesen"? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
TDM Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 Dispose ist dann sinnvoll, wenn du unmanaged-Ressourcen verwaltest. ... u.A. aber auch eine Möglichkeit Weak Events zu implementieren ... :floet: Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
lilith2k3 Geschrieben 15. September 2010 Teilen Geschrieben 15. September 2010 nur mal so in die Runde geworfen ... Wie sieht's denn mit der using-Anweisung aus, die nach dem Verlassen des Blocks schnellstmöglich, darin enthaltene Objekte zerstört? Vielleicht kannst Du dadurch schon einiges an Platz sparen:] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
.NETter Geschrieben 16. September 2010 Teilen Geschrieben 16. September 2010 Es ist durchaus manchmal vorteilhaft den GC manuell anzustoßen. Auch wenn viele der Meinung zu sein scheinen, dass der Mechanismus des GC "gottgegeben genial" ist. Er arbeitet zugegebener Weise recht gut. Sind Ressourcen allerdings sehr knapp kann es sehr wohl einen Vorteil bieten den GC per Hand zu bemühen. Der GC ist ein Dienst mit sehr niedriger Priorität, was bedeutet dass dieser natürlich nur dann seinen Dienst aufnimmt wenn genügend CPU-Zeit zur Verfügung steht oder die Ressourcen sehr kritisch werden. Der GC speichert Informationen zu allen referenzlosen Objekten der 0´ten (nullten) Generation. Ohne ein explizites .Dispose() (und .SuppressFinalize...) am Objekt wird der GC dieses Object an den Finalizer übergeben. Dieser wird wiederum in einem nächsten Zyklus (also schon 2) die Finalize-Methode aufrufen. Wenn jetzt z.B. die CPU-Zeit wieder knapp werden sollte wird der GC seine Arbeit wieder einstellen und keine weiteren Generationen von Objekten mehr bearbeiten und sie werden im Speicher weiterleben. Im übrigen nutzen wir das "ALLE" jeden Tag in unserem Code! using (SqlCommand cmd = new SqlCommand(...)) { // Code... } Um einen "using"-Block nutzen zu können muss das dort instanzierte Objekt IDisposable implementieren! Bei der schließenden Klammer wird dann intern explizit die Methode ... .Dispose() aufgerufen. Man sollte das manuelle anstoßen des GC nur gezielt einsetzen, das ist korrekt. Wenn eine manuelle Optimierung der Speicherressourcen aber nötig ist kann man dies auch guten Gewissens tun. Kleiner Ausschnitt aus dem MSDN: Eine Dispose-Methode sollte die SuppressFinalize-Methode für das Objekt aufrufen, das es freigibt.Wenn sich das Objekt gegenwärtig in der Finalisierungswarteschlange befindet, verhindert SuppressFinalize, dass dessen Finalize-Methode aufgerufen wird.Beachten Sie, dass das Ausführen einer Finalize-Methode hohen Leistungsaufwand erfordert.Wenn Sie das Objekt bereits mit der Dispose-Methode bereinigt haben, muss die Finalize-Methode des Objekts nicht mehr vom Garbage Collector aufgerufen werden. Gruß, Thomas Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
errox Geschrieben 16. September 2010 Autor Teilen Geschrieben 16. September 2010 Also ich hab das nochmal mit Dispose() getestet und allem. Ich bleib dabei: Instanz auf null setzen und den GC aufrufen. Trozdem vielen Dank! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Guybrush Threepwood Geschrieben 16. September 2010 Teilen Geschrieben 16. September 2010 Der GC ist ein Dienst mit sehr niedriger Priorität, was bedeutet dass dieser natürlich nur dann seinen Dienst aufnimmt wenn genügend CPU-Zeit zur Verfügung steht oder die Ressourcen sehr kritisch werden. Und was davon ist jetzt wie ein Argument dafür den selber nochmal anzustoßen? :confused: System ist in der Lage den Dienst laufen zu lassen -> er läuft System ist nicht in der Lage ihn laufen zu lassen -> er läuft nicht System hat zu wenig Resourcen -> er läuft System hat genügend Resourcen -> er läuft nicht Was willst du da in deinem Programm besser entscheiden? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
.NETter Geschrieben 17. September 2010 Teilen Geschrieben 17. September 2010 Zum Beispiel um mehr Arbeitsspeicher für Anwendungen frei zu geben. Wie auch der SQL Server nutzen manche Anwendungen so viel Arbeitsspeicher wie zur Verfügung steht, geben diesen aber sofort frei wenn andere Anwendungen ihn benötigen. Beispiel SQl Server... Es ist genügend RAM für alle Anwendungen frei, was heißt der GC läuft nur los wenn er es gerade für richtig hält und genügend CPU-Zeit verfügbar ist. Der Speicher den ich nun mit meinen Objekten belege, die eigentlich entsorgt werden könnten, bleibt belegt und der SQL Server kann ihn nichts nutzen, was dazu führt, dass er nicht so viele Daten in den Speicher laden kann wie er gerne würde und immer wieder auf die Platte zugreifen muss um Abfragen bedienen zu können. Das hat zur Folge das der SQL Server "langsamer" wird obwohl eigentlich mehr Speicher (den ich mit meinen entsorgbaren Objekten belege) zur Verfügung stehen könnte. Der GC wird keine Speicherknappheit erkennen, da der SQL Server nicht mehr Speicher anfordert und eben nur den nutzt der auch zur Verfügung steht. Habe ich nun eine Anwendung geschrieben die auch noch hohe CPU-Zeit erfordert, was den GC-Durchlauf zeitlich erstmal weiter nach hinten schiebt, wird der SQL Server immer mehr Speicher frei geben um Platz für meinen Objekte-Friedhof zu machen. Irgendwann wird der GC dann greifen, aber bis dahin geht die Performance vom SQL Server oder einer anderen Anwendung erstmal runter. Das ist denke ich ein guter Grund den GC durchaus mal von Hand zu bemühen. Natürlich, wie gesagt immer gezielt. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.