Moja dva centa na GC.Collect metoda u C #

Metoda GC.Collect () već je dugo popularna među programerima .Net. Međutim, rijetko tko od nas zna kako to zapravo funkcionira ili ako je poziv uopće potreban.

CLR (Common Language Runtime) prihvaća prikupljanje smeća kao mehanizam za čišćenje resursa koje vaša aplikacija troši. Imajte na umu da kada stvarate objekte u .Netu, oni se pohranjuju u upravljanu hrpu, a kada završite s upotrebom, ne morate brinuti da ćete ih očistiti - runtime bi to učinio umjesto vas.

CLR organizira upravljanu hrpu u generacije. Tri generacije u koje se organizira upravljana hrpa su: generacija 0, generacija 1 i generacija 2. GC je vješt u povratku memorije koju zauzimaju upravljani objekti. Međutim, trebali biste se pridržavati određenih smjernica kako biste olakšali brže odvoz smeća kako biste poboljšali izvedbu svoje aplikacije.

Trebam li koristiti metodu GC.Collect ()?

Prvo, trebate li uopće nazvati GC.Prikupiti kod svoje aplikacije? Odgovor je u većini slučajeva negativan. Dopustite mi da vam sada kažem što ova metoda radi i zašto biste se u većini slučajeva trebali suzdržati od pozivanja ove metode.

Kada uputite poziv metodi GC.Collect (), vrijeme izvođenja izvodi hodanje nizom kako bi utvrdio objekte koji su dostupni i koji nisu. Također zamrzava glavnu nit (i također sve podređene niti koje je stvorio) aplikacije. Drugim riječima, kada se pozove metoda GC.Collect (), vrijeme izvođenja izvodi blokirajuće prikupljanje smeća svih generacija.

Uvijek bih radije ne upotrebljavao GC.Collect () osim ako postoji određeni razlog za njegovu upotrebu. GC se obično sastoji od faza Mark i Sweep nakon čega slijedi faza zbijanja. Vrijeme provedeno tijekom izvođenja GC-a može postati usko grlo, zato ga koristite vrlo rijetko i ako zaista trebate. Rico Mariani kaže: "Razmislite o pozivu GC.Collect () ako se neki nepovratni događaj upravo dogodio i ako je velika vjerojatnost da je ovaj događaj umro mnogo starih predmeta."

Upotrebom metode GC.Collect ()

Evo kako možete pozvati metodu GC.Collect () u svom kodu.

GC.Collect();

Imajte na umu da možete sakupljati i predmete koji se odnose na određenu generaciju.

GC.Collect() - koristi se za prikupljanje predmeta prisutnih u generacijama 0, 1, 2

GC.Collect(0) - koristi se za prikupljanje predmeta prisutnih u generaciji 0

GC.Collect(1) - koristi se za prikupljanje predmeta prisutnih u generacijama 0 i

Također možete utvrditi koliko je memorije oslobođeno pozivanjem metode GC.Collect (). Da biste to učinili, možete iskoristiti metodu System.GC.GetTotalMemory () kako je prikazano u isječku koda u nastavku.

//Write code to create some large objects here

Console.WriteLine("Total available memory before collection: {0:N0}", System.GC.GetTotalMemory(false));

System.GC.Collect();

Console.WriteLine("Total available memory collection: {0:N0}", System.GC.GetTotalMemory(true));

Metoda GC.GetGeneration () može se koristiti za poznavanje generacije kojoj objekt pripada. Pogledajte dolje navedeni popis kodova.

static void Main(string[] args)

       {

           List obj = new List() { "Joydip", "Steve" };

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           Console.Read();

       }

Kada izvršite gornji program, evo što se ispisuje u prozoru konzole.

0

1

2

Kao što vidite, svaki poziv metodi GC.Collect () promovira objekt "obj" u sljedeću višu generaciju. To je zato što objekt "obj" preživljava prikupljanje smeća u svakom od dva slučaja, tj. Nije povrat niti u jednom od dva poziva upućena metodi GC.Collect ().

Skupljanje smeća možete prisiliti na sve tri generacije ili na određenu generaciju pomoću metode GC.Collect (). Metoda GC.Collect () je preopterećena - možete je nazvati bez ikakvih parametara ili čak tako što ćete sakupljaču smeća proslijediti broj generacije koji želite.

Napominjemo da se objekti koji imaju finalizatore (i ako poziv na SuppressFinalize metodu nije izvršen) neće sakupljati kada se uputi poziv metodi GC.Collect (). Umjesto toga, takvi bi se objekti stavili u red za finalizaciju. Ako želite prikupiti i te objekte, morat ćete uputiti poziv metodi GC.WaitForPendingFinalizers () tako da se ti objekti očiste kad se pokrene sljedeći GC ciklus. U osnovi, povrat memorije koju zauzimaju objekti koji imaju implementirane finalizatore zahtijeva dva prolaza jer su takvi objekti smješteni u red za finalizaciju, a ne da bi bili vraćeni u prvom prolazu kada se sakupljač smeća pokrene.