2016-01-25 24 views
5

Die Frage ist nur für Forschungszwecke.Wird Garbage Collection unmittelbar nach GC.Collect() ausgeführt?

Ich habe viele Bücher über C# gelesen und diese Frage kommt mir immer in den Sinn. Was ich verstanden habe, dass C# verwalteter Code ist und alle Garbage Collection stattfindet, wenn CLR entscheidet, wann Garbage Collection ausgeführt wird. Lasst uns beginnen.

Lasst uns vorstellen, dass ich einfach Klasse Student:

public class Student 
{ 
    public int IdStudent { get; set; } 
    public string Name { get; set; } 
    public string Surname { get; set; } 
} 
class Program 
{ 
     static void Main(string[] args) 
     { 
This is row1: Person person = new Person() {IdPerson=1, Name="Bill", SurName="Collins"}; 
This is row2: System.GC.Collect(); 
This is row3: string str="Hello World!"; 
    }   
} 

Bitte, genehmigen oder meine Vermutungen ablehnen:

  1. Bin ich richtig, dass die Garbage Collection nicht sofort ausgeführt wird bei row2?
  2. GC.Collect() ist nur eine Anfrage um eine Garbage Collection zu machen, die nicht sofort in row2 ausgeführt wird. Diese Zeile wird möglicherweise in x Millisekunden/Sekunden ausgeführt. Meiner Meinung nach Methode System.GC.Collect(); sagt nur Garbage Collector, der Garbage Collector Garbage Collection laufen soll, aber echte Garbage Collection in x Millisekunden/Sekunde

  3. Nur Garbage Collector weiß, wann die Garbage Collection ausgeführt wird auftreten können. Und wenn es freier Platz in Generation 0 ist, dann Garbage Collection wird nicht auftreten, in dem row2:row2: System.GC.Collect();

  4. Es ist nicht möglich, die Garbage Collection läuft sofort, wie wir in verwalteten Umgebung programmieren und nur CLR entscheidet, wann Garbage Collection ausführen. Garbage Collection kann in x Millisekunden/Sekunden ausgeführt werden, oder Garbage Collection möglicherweise nicht ausführen, da in Generation 0 genügend Platz vorhanden ist, um neue Objekte nach Aufruf der Methode GC.Collect() zu erstellen. Was der Programmierer tun kann, ist CLR, um die Garbage Collection nach der Methode GC.Collect() zu starten.

Update:

ich this msdn article about GC.Collect Method(). gelesen habe. Es ist mir jedoch unklar, wann ein echtes Clearing von nicht referenzierten Objekten gestartet wird. MSDN sagt:

GC.Collect-Methode() erzwingt eine sofortige Garbage Collection aller -Generationen.

Verwenden Sie diese Methode, um zu versuchen den gesamten Speicher zurückzufordern, die nicht zugänglich ist:

jedoch in Bemerkungen Ich habe diese ein zu lesen. Es führt eine blockierende Garbage Collection aller Generationen durch.

  1. ich damit bin verwirrt „Mit dieser Methode können TRY“ und ich denke, dass die Garbage Collection nicht Ursache CLR entscheidet auftreten kann, dass genügend Platz vorhanden ist um neue Objekte zu erstellen. Habe ich recht?
+1

Oh es läuft definitiv, aber fragen Sie, ob es etwas bestimmtes sammelt? – Sayse

+0

@Sayse Ja, sammelt GC unreferenzierte Objekte? – StepUp

+0

Die [GC.Collect] (https://msdn.microsoft.com/en-us/library/xe0c2357 (v = vs.110) .aspx) Dokumentation enthält einige der Antworten .. – user2864740

Antwort

4

kurze Antwort

GC.Collect() Aufruf wird eine vollständige Garbage Collection tun und warten, bis es zu beenden, aber es wird nicht für alle ausstehenden Finalizers warten zu laufen.

lange Antwort

Sie sind zum Teil in Ihren Vermutungen richtig, weil die GC für den Betrieb Finalizers läuft in einem oder mehrere Hintergrund-Threads. (Aber siehe Fußnote am Ende dieser Antwort.)

Es ist jedoch möglich ist, für eine vollständige GC zu warten, durch den Aufruf GC.WaitForFullGCComplete() und GC.WaitForPendingFinalizers() zu beenden, nachdem Sie GC.Collect() genannt haben:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.WaitForFullGCComplete(); 

Beachten Sie jedoch, dass Der Thread, auf dem Finalizer ausgeführt werden, ist nicht angegeben, so gibt es keine Garantie, dass diese Methode beendet wird.

Beachten Sie, dass Sie normalerweise nicht sollte den GC auf diese Weise verwenden; Ich nehme an, Sie haben einen speziellen Fall, den Sie ansprechen müssen, oder Sie tun dies für Forschungszwecke. Der einzige gültige Fall, den ich gesehen habe, ist, wenn eine Anwendung geschlossen wird und Sie versuchen (sicherstellen) möchten, dass alle Finalizer ausgeführt wurden - weil sie zum Beispiel Protokolldateien usw. leeren.

Wie oben erwähnt, kann damit nicht garantiert werden, dass alle Finalizer ausgeführt wurden. es ist nur das Beste, was du tun kannst.

In Antwort auf Ihren Punkt (5):

Die Dokumentation für GC.Collect() heißt es:

Erzwingt eine sofortige Garbage-Collection aller Generationen.

So wird erzwingen einen GC.

Die Dokumentation auch heißt:

Verwenden Sie diese Methode, um zu versuchen den gesamten Speicher zurückzufordern, die nicht zugänglich ist.

Die Verwendung des Wortes "try" bedeutet lediglich, dass selbst wenn ein vollständiger GC ausgeführt wird, nicht der gesamte nicht zugreifbare Speicher notwendigerweise zurückgewonnen wird. Es gibt verschiedene Gründe, die zum Beispiel auftreten können, wenn ein Finalizer blockiert.

Fußnote

.Net 4.5 allows you to specify whether GC.Collect() is blocking or not.

In der Tat, die Dokumentation für GC.Collect() besagt, dass Es führt eine blockierende Garbage Collection aller Generationen, die meinen obigen Aussagen widersprechen würde. Es scheint jedoch einige Verwirrung darüber zu bestehen, ob dies wirklich der Fall ist.

Siehe zum Beispiel this thread. diese

Die Antwort lautet: GC.Collect() wird standardmäßig Wartezeit für alle Generationen GCed sein, aber es wird nicht für anhängigen Finalizers warten, die in einem separaten Thread immer ausgeführt werden.

Wenn Sie also nicht auf Finalizer warten müssen, müssen Sie nur GC.Collect() anrufen und Sie müssen nicht auf etwas anderes warten.

+0

Diese Frage ist nur für Forschungszwecke. Bitte beantworten Sie die Frage der UPDATE-Sektion meiner Frage. – StepUp

+0

zum Abschluss 'GC.Collect()' wird nicht IMMEDIATE Garbage Collection nach dem Aufruf von 'GC.Collect()'? nur 'ja' oder' nein' – StepUp

+1

@StepUp 'GC.Collect()' wird eine sofortige Garbage Collection erzwingen und warten bis es fertig ist (vollständige Garbage Collection) EXCEPT für ausstehende Finalizer, die in einem separaten Thread ausgeführt werden. Ich habe etwas am Anfang meiner Antwort geschrieben, um dies zu betonen. –

1

Es gibt zwei GCs und von Ihrem Code glaube ich, dass Sie über Workstation GC wissen möchten. Welche Pausen minimieren Sie, indem Sie während vollständiger Sammlungen gleichzeitig ausgeführt werden? Der Workstation-GC verwendet den zweiten Prozessor, um die Sammlung gleichzeitig auszuführen, wodurch Verzögerungen minimiert und der Durchsatz verringert wird. Wir sollten uns nur um GC-Verhalten sorgen, wenn der Server GC seine Aufgabe nicht ordnungsgemäß erfüllt. Wenn Sie GC.collect() in Ihrem Code wie dem GC der Arbeitsstation hinzufügen, kann das auf Server-GC sinnlos sein.

Der Server GC ist auf maximalen Durchsatz ausgelegt und skaliert mit sehr hoher Leistung. Die Speicherfragmentierung auf Servern ist ein wesentlich schwerwiegenderes Problem als auf Workstations, was die Speicherbereinigung zu einem attraktiven Angebot macht. In einem Einprozessor-Szenario arbeiten beide Kollektoren auf die gleiche Weise: Workstation-Modus, ohne gleichzeitige Sammlung

Ich bin von dieser Verwenden Sie diese Methode verwechselt TRY und ich denke, dass die Garbage Collection nicht Ursache CLR entscheidet auftreten kann, dass es genug ist Platz zum Erstellen neuer Objekte. Habe ich recht?

Für workstaion GC wird GC.Collect beginnen so bald wie möglich zu sammeln, können Sie davon ausgehen, sicher sie sofort sammeln.