Programování

Moje dva centy na metodě GC.Collect v C #

Metoda GC.Collect () je již dlouho populární mezi vývojáři .Net. Málokdo z nás však ví, jak to ve skutečnosti funguje, nebo zda je vůbec nutné jej zavolat.

CLR (Common Language Runtime) přijímá sběr odpadků jako mechanismus k vyčištění prostředků spotřebovaných vaší aplikací. Všimněte si, že když vytváříte objekty v .Net, ukládají se do spravované hromady a když je budete používat, nemusíte si dělat starosti s jejich čištěním - běhový modul by to udělal za vás.

CLR organizuje spravovanou hromadu do generací. Tři generace, do kterých je spravovaná halda organizována, jsou: Generace 0, Generace 1 a Generace 2. GC je zběhlý v získávání paměti obsazené spravovanými objekty. Měli byste se však řídit určitými pokyny, které usnadní rychlejší uvolňování paměti, aby se zlepšil výkon vaší aplikace.

Mám použít metodu GC.Collect ()?

Nejprve musíte vůbec zavolat GC.Collect v kódu své aplikace? Odpověď je ve většině případů ne. Nyní vám řeknu, co tato metoda dělá a proč byste se měli zdržet volání této metody ve většině případů.

Když zavoláte metodu GC.Collect (), modul runtime provede procházení zásobníku a určí objekty, které jsou dosažitelné a ty, které nejsou. Také zmrazí hlavní vlákno (a také všechna podřízená vlákna, která vytvořila) aplikace. Jinými slovy, když se volá metoda GC.Collect (), modul runtime provede blokování uvolňování paměti všech generací.

Vždy bych raději nepoužíval GC.Collect (), pokud pro to není konkrétní důvod. GC se obvykle skládá z fází Mark a Sweep následovaných fází zhutnění. Čas, který modul runtime strávil provedením GC, se může stát překážkou, proto jej používejte jen velmi zřídka a pokud to opravdu potřebujete. Rico Mariani uvádí: „Zvažte volání GC.Collect (), pokud právě došlo k nějaké neopakující se události a tato událost s vysokou pravděpodobností způsobila smrt mnoha starých objektů.“

Pomocí metody GC.Collect ()

Zde je způsob, jak můžete v kódu vyvolat metodu GC.Collect ().

GC.Collect ();

Všimněte si, že můžete také sbírat objekty, které se týkají konkrétní generace.

GC.Collect () - slouží ke sběru předmětů přítomných v generacích 0, 1, 2

GC.Collect (0) - slouží ke sběru předmětů přítomných v generaci 0

GC. Kolekce (1) - slouží ke sběru předmětů přítomných v generacích 0 a

Voláním metody GC.Collect () můžete také určit, kolik paměti bylo uvolněno. Chcete-li to provést, můžete využít metodu System.GC.GetTotalMemory (), jak je ukázáno v fragmentu kódu níže.

// Napište kód a vytvořte zde velké objekty

Console.WriteLine ("Celková dostupná paměť před sběrem: {0: N0}", System.GC.GetTotalMemory (false));

System.GC.Collect ();

Console.WriteLine ("Celková dostupná paměť: {0: N0}", System.GC.GetTotalMemory (true));

Metodu GC.GetGeneration () lze použít ke zjištění generace, ke které objekt patří. Viz seznam kódů uvedený níže.

static void Main (řetězec [] 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 ();

       }

Když spustíte výše uvedený program, v okně konzoly se vytiskne toto.

0

1

2

Jak vidíte, každé volání metody GC.Collect () propaguje objekt „obj“ na další vyšší generaci. Důvodem je, že objekt "obj" přežije uvolňování paměti v každém ze dvou případů, tj. Není uvolněn v žádném ze dvou volání provedených metodou GC.Collect ().

Sbírání odpadků můžete vynutit buď na všechny tři generace, nebo na konkrétní generaci pomocí metody GC.Collect (). Metoda GC.Collect () je přetížená - můžete ji volat bez jakýchkoli parametrů nebo dokonce předáním generačního čísla, které byste chtěli sbírat odpadky.

Všimněte si, že objekty, které mají finalizátory (a pokud nebylo provedeno volání metody SuppressFinalize), nebudou shromážděny při volání metody GC.Collect (). Spíše by takové objekty byly umístěny do finalizační fronty. Pokud byste chtěli shromáždit i tyto objekty, budete muset zavolat metodu GC.WaitForPendingFinalizers (), aby se tyto objekty vyčistily při spuštění dalšího cyklu GC. V zásadě vyžaduje uvolnění paměti obsazené objekty, které mají implementované finalizátory, dva průchody, protože takové objekty jsou umístěny do finalizační fronty, místo aby byly znovu získány v prvním průchodu při spuštění garbage collectoru.