GC.Collect'i aramak ne zaman kabul edilebilir?


166

Genel tavsiye, GC.Collectkodunuzdan arama yapmamanızdır , ancak bu kuralın istisnaları nelerdir?

Sadece bir çöp toplama zorlamanın mantıklı olabileceği birkaç özel durumu düşünebilirim.

Akla gelen örneklerden biri, aralıklarla uyanan, bazı görevleri yerine getiren ve uzun süre uyuyan bir hizmettir. Bu durumda, boşta kalacağınız sürecin gerekenden daha fazla belleğe tutunmasını önlemek için bir koleksiyonu zorlamak iyi bir fikir olabilir.

Aramanın kabul edilebilir olduğu başka durumlar var GC.Collectmı?


Yanıtlar:


153

Önemli bir nesne grubunun - özellikle 1. ve 2. nesillerde olduğundan şüphelenilenlerin - artık çöp toplama için uygun olduğuna ve şimdi küçük performans isabeti açısından toplamak için uygun bir zaman olduğuna inanmak için iyi bir nedeniniz varsa. .

Bunun iyi bir örneği, sadece büyük bir formu kapattıysanız. Artık tüm UI denetimlerinin çöp toplanabileceğini biliyorsunuz ve form kapandığı için çok kısa bir duraklama muhtemelen kullanıcı tarafından fark edilmeyecek.

GÜNCELLEME 2.7.2018

.NET 4.5 itibariyle - GCLatencyMode.LowLatencyve vardır GCLatencyMode.SustainedLowLatency. Bu modlardan herhangi birine girip çıkarken, tam bir GC'yiGC.Collect(2, GCCollectionMode.Forced) .

.NET 4.6'dan itibaren - GC.TryStartNoGCRegionyöntem (salt okunur değeri ayarlamak için kullanılır)GCLatencyMode.NoGCRegion ). Bu, yeterli belleği boşaltmak için tam bir engelleme çöpü toplama gerçekleştirebilir, ancak bir süre GC'yi reddettiğimiz göz önüne alındığında, tam GC'yi önce ve sonra yapmanın iyi bir fikir olduğunu iddia ederim.

Kaynak: Microsoft mühendisi Ben Watson: Yüksek Performanslı .NET Kodu Yazma , 2. Baskı. 2018.

Görmek:


8
GC.Collect (2) 'yi çağıran MS kaynak koduna göre her 850 ms'de bir sorun yok. İnanmıyor musunuz? Sonra sadece PresentationCore.dll, MS.Internal.MemoryPressure.ProcessAdd () 'a bakın. Şu anda bir görüntü işleme uygulaması (küçük resimler, gerçek bellek basıncı ile hiçbir şey) var.
springy76

36
@ springy76: bu o vererek tavsiye tarafından iyi bir şey olarak kabul anlamına gelmez tek bir yerde Microsoft tarafından yapılan Being gelen ... Microsoft
Jon Skeet

4
Bu örneği sevmiyorum. Form kapatıldıktan sonra bunu yapan şey nedir? Gördüğüm iyi bir örnek, XBox veya WindowsPhone'a oyun seviyesini yükledikten sonra. Bu platformlarda GC, 1MB veya sth ayırdıktan sonra çalışır. Bu yüzden seviyenin yüklenmesi sırasında olabildiğince tahsis etmek (bazı açılış ekranını gösterirken) ve daha sonra GC.Collect'i yapmak oyun sırasında koleksiyonlardan kaçınmak için iyidir.
Piotr Perak

8
@Peri: Form kapatıldıktan sonra bunu yapmanın amacı, çöp toplama için uygun olan bir grup nesneyi (kontroller, görüntülemekte olduğunuz veriler) yapmış olmanızdır; yani, çağırarak GC.Collecttemelde bildiğiniz çöp toplayıcıya söylediğinizi bir değişiklik için daha iyi. Örneği neden sevmiyorsun?
Jon Skeet

6
@ SHCJ: GC.Collect()GC'nin tam bir koleksiyon gerçekleştirmesini isteyecektir . Size sadece çöp toplama için uygun önceden uzun ömürlü nesnelerin çok yaptık biliyorsanız ve kullanıcı sonra yerine şimdi az olasılıkla hafif duraklama fark olduğuna inanıyoruz, o şimdi daha iyi olduğunu düşünmek oldukça makuldür daha sonra gerçekleşmesine izin vermekten ziyade bir koleksiyonu sorma zamanı geldi.
Jon Skeet

50

GC.CollectSadece ham performans / profil oluşturucu test makineleri yazarken kullanıyorum ; Yani test etmek için kod iki (veya daha fazla) blok var - gibi bir şey:

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestA(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestB(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
...

Böylece TestA()ve TestB()mümkün olduğunca benzer bir durumla çalıştırın - yani TestB()sadece TestAdevrilme noktasına çok yakın olduğu için dövülmez.

Klasik bir örnek, Mainilmekli dize birleştirme ve arasındaki farkı gösteren basit bir konsol exe ( örneğin buraya gönderilecek kadar yeterli bir yöntem) olacaktır StringBuilder.

Kesin bir şeye ihtiyacım olursa, bu tamamen bağımsız iki test olacaktır - ancak davranışlar hakkında kaba bir his elde etmek için testler sırasında GC'yi en aza indirmek (veya normalleştirmek) için genellikle bu yeterlidir.

Üretim kodu sırasında? Henüz kullanmadım ;-p


1
Ve muhtemelen bu durumda da "WaitForPendingFinalizers" (ya da her ne ise) eklerim ;-p
Marc Gravell

29

En iyi uygulama, çoğu durumda bir çöp toplama işlemini zorlamamaktır. (Üzerinde çalıştığım her sistem, zorla çöp toplamalarına sahipti, çözüldüğünde çöp toplama zorlama ihtiyacını ortadan kaldıracak ve sistemi büyük ölçüde hızlandıracak problemlerin altını çiziyordu.)

Bir var birkaç durum olduğunda sizi daha sonra çöp toplayıcı yapar bellek kullanımı hakkında daha fazla bilgi. Bu, çok kullanıcılı bir uygulamada veya bir seferde birden fazla isteğe yanıt veren bir hizmette doğru olmayabilir.

Bununla birlikte, bazı parti tipi işlemlerde GC'den daha fazlasını biliyorsunuzdur. Örneğin bir uygulamayı düşünün.

  • Komut satırında dosya adlarının bir listesi verilir
  • Tek bir dosyayı işler ve sonucu bir sonuç dosyasına yazar.
  • Dosya işlenirken, dosyanın işlenmesi tamamlanana kadar toplanamayan çok sayıda birbirine bağlı nesne oluşturur (örneğin, ayrıştırma ağacı)
  • İşlediği dosyalar arasında eşleşme durumunu tutmaz .

Sen may her dosyayı işlemek zorunda sonra tam bir çöp toplama zorlamak gerektiğini test (dikkatli sonra) dava yapabilmek.

Başka bir durum, bazı öğeleri işlemek için birkaç dakikada bir uyanan ve uykudayken herhangi bir durumu tutmayan bir hizmettir . Sonra tam bir koleksiyonu uyumadan hemen önce zorlamak faydalı olabilir .

Bir koleksiyonu zorlamayı düşünebileceğim tek zaman, son zamanlarda çok sayıda nesnenin oluşturulduğunu ve şu anda çok az nesneye başvurulduğunu bildiğim zamandır.

Ben kendimi bir GC zorlamak zorunda kalmadan bu tür bir şey hakkında ipuçları verebilir zaman ben bir çöp toplama API olurdu.

Ayrıca bkz. " Rico Mariani'nin Performans Tidbitleri "



11

Büyük 7/24 veya 7/24 sistemlerde - iletilere, RPC isteklerine tepki veren veya bir veritabanını veya işlemi sürekli olarak yok eden sistemler - bellek sızıntılarını tanımlamanın bir yolunu bulmak yararlıdır. Bunun için, herhangi bir işlemi geçici olarak askıya almak ve daha sonra tam çöp toplama gerçekleştirmek için uygulamaya bir mekanizma ekleme eğilimindeyim. Bu, sistemi, kalan belleğin yasal olarak uzun ömürlü bellek (önbellekler, yapılandırma & c.) Olduğu veya başka bir şekilde 'sızdırıldığı' (köklü olması beklenmeyen veya köklendirilmesi istenen ancak gerçekte olan) durgun bir duruma sokar.

Bu mekanizmaya sahip olmak, raporların etkin işlemden kaynaklanan gürültü ile bulanıklaştırılmayacağı için bellek kullanımını profil haline getirmeyi çok daha kolay hale getirir.

Tüm çöpleri aldığınızdan emin olmak için iki koleksiyon yapmanız gerekir:

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

İlk koleksiyon, finalizörlere sahip herhangi bir nesnenin sonlandırılmasına neden olacağından (ancak aslında bu nesneleri çöp toplamak değil). İkinci GC bu nihai nesneleri toplayacak.


İki geçişli koleksiyonu şimdi birkaç yerde gördüm, ancak GC.WaitForPendingFinalizers için MSDN belgelerindeki pasajı okuduktan sonra : "Devam etmeden önce tüm finalizerlerin tamamlanmasını bekleyin. GC.WaitForPendingFinalizers'a bu çağrı olmadan, aşağıdaki çalışan döngü sonlandırıcılar ile aynı anda yürütülebilir. Bu çağrı ile çalışan döngü yalnızca tüm sonlandırıcılar çağrıldıktan sonra yürütülür. " Ben sadece bir dokunuş paranoyağım. İki geçiş yapmak için kesin bir kaynak biliyor musunuz?
jerhewet

1
@jerhewet: Neden iki koleksiyonun gerekli olduğunu anlamanın anahtarı, finalizörlere sahip nesnelere ne olduğunu anlamaktır. Ne yazık ki tam olarak istediğin şey yok, ama bu makaleyi ve bu soruyu SO hakkında okudum .
Paul Ruane

10

Çöp toplayıcının uygulama hakkında doğası hakkında bir şey bildiğinizde GC.Collect () çağırabilirsiniz. Yazar olarak bunun çok muhtemel olduğunu düşünmek cazip gelebilir. Bununla birlikte, gerçek şu ki, GC oldukça iyi yazılmış ve test edilmiş bir uzman sisteme karşılık gelir ve düşük seviyeli kod yolları hakkında bir şey bilmeniz nadirdir.

Bazı ekstra bilgilere sahip olabileceğinizi düşünebileceğim en iyi örnek, boşta kalma süreleri ile çok yoğun dönemler arasında geçiş yapan bir uygulamadır. Yoğun dönemler için mümkün olan en iyi performansı istiyorsunuz ve bu nedenle biraz temizlik yapmak için boşta kalma süresini kullanmak istiyorsunuz.

Bununla birlikte, çoğu zaman GC bunu yapmak için yeterince akıllıdır.


8

Bir bellek parçalanması çözümü olarak. Bir bellek akışına (ağ akışından okuma) çok fazla veri yazarken bellek istisnalarından çıkıyordum. Veriler 8K yığın halinde yazılmıştır. 128M'ye ulaştıktan sonra, çok fazla bellek olmasına rağmen istisna vardı (ancak parçalanmıştı). GC.Collect () öğesini çağırmak sorunu çözdü. Düzeltmeden sonra 1G'nin üstesinden gelebildim.


7

Rico Mariani'nin bu makalesine bir göz atın. GC.Collect'i çağırmak için iki kural verir (kural 1: "Yapma"):

GC.Collect () ne zaman çağrılır


3
Zaten oradaydım. Yapmamanız gereken bir şey yapmak için mazeretler bulmaya çalışmıyorum, ancak kabul edilebilir olacağı özel durumlar olup olmadığını bilmek istiyorum.
Brian Rasmussen

5

GC.Collect () yöntemini çağırmanın neredeyse gerekli olduğu bir örnek, Microsoft Office'i Interop aracılığıyla otomatikleştirmektir. Office için COM nesneleri otomatik olarak serbest bırakılmayı sevmez ve Office ürününün çok fazla miktarda bellek kaplamasına neden olabilir. Bunun bir sorun mu yoksa tasarım gereği mi olduğundan emin değilim. İnternette bu konuyla ilgili çok fazla yayın var, bu yüzden çok fazla ayrıntıya girmeyeceğim.

Interop kullanarak programlama yaparken , genellikle Marshal.ReleseComObject () kullanımı ile birlikte her bir COM nesnesi manuel olarak serbest bırakılmalıdır. Ayrıca, Çöp Toplama'yı manuel olarak çağırmak biraz "temizlemeye" yardımcı olabilir. Interop nesnelerini tamamladığınızda aşağıdaki kodu çağırmak biraz yardımcı olur:

GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()

Kişisel deneyimime göre, ReleaseComObject bir arada kullanmak ve elle çöp toplama çağrısı Office ürünlerinin, özellikle Excel'in bellek kullanımını büyük ölçüde azaltır.


evet ben com nesneleri üzerinden de çalışır .net erişim excel ile bu koştu. GC operasyonları burada sınırlı olduğu için bunun DEBUG modunda iyi çalışmayacağını belirtmek önemlidir. Yalnızca RELEASE modunda olduğu gibi çalışacaktır. ilgili bağlantı: stackoverflow.com/questions/17130382/…
Blechdose

5

Dizi ve listede bazı performans testleri yapıyordum:

private static int count = 100000000;
private static List<int> GetSomeNumbers_List_int()
{
    var lstNumbers = new List<int>();
    for(var i = 1; i <= count; i++)
    {
        lstNumbers.Add(i);
    }
    return lstNumbers;
}
private static int[] GetSomeNumbers_Array()
{
    var lstNumbers = new int[count];
    for (var i = 1; i <= count; i++)
    {
        lstNumbers[i-1] = i + 1;
    }
    return lstNumbers;
}
private static int[] GetSomeNumbers_Enumerable_Range()
{
    return  Enumerable.Range(1, count).ToArray();
}

static void performance_100_Million()
{
    var sw = new Stopwatch();

    sw.Start();
    var numbers1 = GetSomeNumbers_List_int();
    sw.Stop();
    //numbers1 = null;
    //GC.Collect();
    Console.WriteLine(String.Format("\"List<int>\" took {0} milliseconds", sw.ElapsedMilliseconds));

    sw.Reset();
    sw.Start();
    var numbers2 = GetSomeNumbers_Array();
    sw.Stop();
    //numbers2 = null;
    //GC.Collect();
    Console.WriteLine(String.Format("\"int[]\" took {0} milliseconds", sw.ElapsedMilliseconds));

    sw.Reset();
    sw.Start();
//getting System.OutOfMemoryException in GetSomeNumbers_Enumerable_Range method
    var numbers3 = GetSomeNumbers_Enumerable_Range();
    sw.Stop();
    //numbers3 = null;
    //GC.Collect();

    Console.WriteLine(String.Format("\"int[]\" Enumerable.Range took {0} milliseconds", sw.ElapsedMilliseconds));
}

ve ben OutOfMemoryExceptionGetSomeNumbers_Enumerable_Range yöntemi var tek geçici çözüm bellek ayırmaktır:

numbers = null;
GC.Collect();

Neden oy vermiyorsun? cevabım GC'yi ne zaman arayacağınızı gösteren bir örnektir. Daha iyi bir öneriniz var mı? Sunmaktan memnuniyet duyarız.
Daniel B

4

Örneğinizde, GC.Collect'i çağırmanın sorun olmadığını düşünüyorum, daha ziyade bir tasarım sorunu var.

Belirli aralıklarla uyanacaksanız (ayarlanan saatler), programınız tek bir yürütme için hazırlanmış olmalıdır (görevi bir kez gerçekleştirin) ve sonra sonlandırın. Ardından, programı zamanlanan aralıklarla çalışacak zamanlanmış görev olarak ayarladınız.

Bu şekilde, GC.Collect'i aramakla kendinizi endişelendirmenize gerek yoktur (ki nadiren yapmanız gerekir ).

Bununla birlikte, Rico Mariani'nin bu konuda harika bir blog yazısı var, burada bulunabilir:

http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx


3

Bellek sızıntısı oluşturmadığınızı doğrulamak istediğinizde GC.Collect () öğesini çağırmak için kullanışlı bir yer (örn. WeakReferences veya ConditionalWeakTable, dinamik olarak oluşturulan kod vb. İle bir şey yapıyorsanız).

Örneğin, benim gibi birkaç test var:

WeakReference w = CodeThatShouldNotMemoryLeak();
Assert.IsTrue(w.IsAlive);
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsFalse(w.IsAlive);

WeakReferences kullanmanın kendi başına bir sorun olduğu iddia edilebilir, ancak böyle bir davranışa dayanan bir sistem oluşturuyorsanız GC.Collect () yöntemini çağırmanın bu kodu doğrulamak için iyi bir yol olduğu görülmektedir.




2
using(var stream = new MemoryStream())
{
   bitmap.Save(stream, ImageFormat.Png);
   techObject.Last().Image = Image.FromStream(stream);
   bitmap.Dispose();

   // Without this code, I had an OutOfMemory exception.
   GC.Collect();
   GC.WaitForPendingFinalizers();
   //
}

2

Üzgün ​​olmaktan daha güvenli olduğu bazı durumlar vardır.

İşte bir durum.

IL yeniden yazmalarını kullanarak C # ' da yönetilmeyen bir DLL yazmak mümkündür (bunun gerekli olduğu durumlar vardır).

Örneğin, diyelim ki DLL sınıf düzeyinde bir bayt dizisi oluşturuyor - çünkü dışa aktarılan işlevlerin çoğunun buna erişmesi gerekiyor. DLL kaldırıldığında ne olur? Çöp toplayıcı otomatik olarak bu noktada çağrılıyor mu? Bilmiyorum, ama yönetilmeyen bir DLL olarak GC denilmez tamamen mümkündür. Ve çağrılmasaydı büyük bir sorun olurdu. DLL kaldırıldığında, çöp toplayıcı da öyle olur - bu yüzden olası çöpleri toplamaktan kim sorumlu olacak ve nasıl yapacaklardı? C # 'nin çöp toplayıcısını kullanmak daha iyidir. Sınıf düzeyi değişkenlerinin null olarak ayarlandığı ve çöp toplayıcısının çağrıldığı bir temizleme işlevine (DLL istemcisi tarafından kullanılabilir) sahip olun.

Eşeği sağlam kazığa bağlamak.


2

bu konuda hala emin değilim. 7 yıldan beri bir Uygulama Sunucusunda çalışıyorum. Daha büyük kurulumlarımız 24 GB RAM kullanıyor. Çok iş parçacıklı ve TÜM GC.Collect () çağrıları gerçekten korkunç performans sorunlarıyla karşılaştı.

Birçok üçüncü taraf Bileşeni, şu anda bunu yapmanın akıllıca olduğunu düşündüklerinde GC.Collect () yöntemini kullanmıştır. Bu nedenle, basit bir Excel Rapor grubu, App Server'ı dakikada birkaç kez tüm iş parçacıkları için engelledi.

GC.Collect () çağrılarını kaldırmak için tüm 3. Taraf Bileşenlerini yeniden düzenlemek zorunda kaldık ve bunu yaptıktan sonra hepsi iyi çalıştı.

Ama ben de Win32 üzerinde sunucuları çalıştırıyorum ve burada bir OutOfMemoryException aldıktan sonra GC.Collect () yoğun kullanmaya başladı.

Ama ben de bu konuda oldukça emin değilim, çünkü sık sık fark ettim, 32 Bit'de bir OOM aldığımda ve GC.Collect () çağırmadan aynı Operasyonu tekrar çalıştırmayı denediğimde, gayet iyi çalıştı.

Ben merak ediyorum bir şey OOM İstisna kendisi ... .Net Framework yazmış ve bir bellek bloğu atayamazsanız, ben GC.Collect (), bellek dolandırmak (??) kullanmak, tekrar deneyin ve eğer hala bir boş hafıza bloğu bulamazsam, o zaman OOM-İstisnasını atarım.

Veya GC.Collect ile performans sorununun dezavantajları nedeniyle en azından bu davranışı yapılandırılabilir seçenek olarak yapın.

Şimdi sorunu "çözmek" için benim app böyle kod bir sürü var:

public static TResult ExecuteOOMAware<T1, T2, TResult>(Func<T1,T2 ,TResult> func, T1 a1, T2 a2)
{

    int oomCounter = 0;
    int maxOOMRetries = 10;
    do
    {
        try
        {
            return func(a1, a2);
        }
        catch (OutOfMemoryException)
        {
            oomCounter++;
            if (maxOOMRetries > 10)
            {
                throw;
            }
            else
            {
                Log.Info("OutOfMemory-Exception caught, Trying to fix. Counter: " + oomCounter.ToString());
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(oomCounter * 10));
                GC.Collect();
            }
        }
    } while (oomCounter < maxOOMRetries);

    // never gets hitted.
    return default(TResult);
}

(Bir ORM Önbellekleme Hizmeti çalıştırdığımızdan ve RAM'in önceden tanımlanmış bazı değerleri aşması durumunda hizmetin önbelleğe alınmış tüm nesneleri serbest bırakması biraz zaman aldığından Thread.Sleep () davranışının gerçekte Uygulamaya özgü bir davranış olduğunu unutmayın. birkaç saniye ilk kez ve her OOM oluşumunda bekleme süresini artırdı.)


Bir Bileşen çağırmamalıdır GC.Collect. Geniş uygulama etkisi olduğu için sadece uygulama bunu yapmalıdır (eğer varsa).
CodesInChaos

If i would have written the .Net Framework, and i can't alloc a memory block, i would use GC.Collect(),- Sanırım bunu zaten yapıyorlar - Dahili GC tetikleyicilerinden birinin bellek ayırmak için bazı başarısızlıklar olduğuna dair göstergeler gördüm.
G. Stoynev

2

Çok pahalı olduğu için GC.Collect () kullanmaktan kaçınmalısınız. İşte bir örnek:

        public void ClearFrame(ulong timeStamp)
    {
        if (RecordSet.Count <= 0) return;
        if (Limit == false)
        {
            var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
            if (seconds <= _preFramesTime) return;
            Limit = true;
            do
            {
                RecordSet.Remove(RecordSet[0]);
            } while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
        }
        else
        {
            RecordSet.Remove(RecordSet[0]);

        }
        GC.Collect(); // AVOID
    }

TEST SONUCU: CPU KULLANIMI% 12

Bunu değiştirdiğinizde:

        public void ClearFrame(ulong timeStamp)
    {
        if (RecordSet.Count <= 0) return;
        if (Limit == false)
        {
            var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
            if (seconds <= _preFramesTime) return;
            Limit = true;
            do
            {
                RecordSet[0].Dispose(); //  Bitmap destroyed!
                RecordSet.Remove(RecordSet[0]);
            } while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
        }
        else
        {
            RecordSet[0].Dispose(); //  Bitmap destroyed!
            RecordSet.Remove(RecordSet[0]);

        }
        //GC.Collect();
    }

TEST SONUCU: CPU KULLANIMI% 2-3


1

Başka bir neden, bir USB COM bağlantı noktasında bir SerialPort açmanız ve ardından USB aygıtının fişinin çekilmesidir. SerialPort açıldığından, kaynak, sistem kayıt defterinde önceden bağlanan bağlantı noktasına bir başvuru tutar. Sistemin kayıt defteri eski verileri içereceğinden , kullanılabilir bağlantı noktaları listesi yanlış olur. Bu nedenle liman kapatılmalıdır.

Bağlantı noktasındaki SerialPort.Close () öğesini çağırmak nesneye Dispose () öğesini çağırır, ancak çöp toplama işlemi gerçekten çalışana kadar bellekte kalır ve çöp toplayıcı kaynağı serbest bırakmaya karar verene kadar kayıt defterinin eski kalmasına neden olur.

Gönderen https://stackoverflow.com/a/58810699/8685342 :

try
{
    if (port != null)
        port.Close(); //this will throw an exception if the port was unplugged
}
catch (Exception ex) //of type 'System.IO.IOException'
{
    System.GC.Collect();
    System.GC.WaitForPendingFinalizers();
}

port = null;

0

Bu soru ile ilgili değildir, ancak .NET (XSLCompiledTranform) içindeki XSLT dönüşümleri için başka seçeneğiniz olmayabilir. Başka bir aday da MSHTML kontrolüdür.



0

GC'yi çağırmanın iyi bir nedeni, Raspberry PI (mono ile çalışan) gibi hafızası az olan küçük ARM bilgisayarlardadır. Ayrılmamış bellek parçaları sistem RAM'inden çok fazla kullanırsa, Linux işletim sistemi kararsız olabilir. Ben bellek taşma sorunları kurtulmak için her saniye (!) GC aramak zorunda bir uygulama var.

Başka bir iyi çözüm, nesneleri artık ihtiyaç duyulmadığında imha etmektir. Ne yazık ki bu pek çok durumda kolay değildir.


0

Küçük nesne yığını (SOH) ve Büyük nesne yığını (LOH) olduğundan

SOP'ta referans nesnesini temizlemek ve canlı nesneyi yeni nesle taşımak için GC.Collect () 'i çağırabiliriz.

.Net4.5, biz kullanarak da kompakt LOH can largeobjectheapcompactionmode


0

Çok sayıda yeni System.Drawing.Bitmapnesne oluşturuyorsanız, Çöp Toplayıcı bunları temizlemez. Nihayetinde GDI + hafızanızın bittiğini düşünecek ve "Parametre geçerli değil" istisnası atacaktır. Bu GC.Collect()kadar sık aramak (çok sık değil!) Bu sorunu çözüyor gibi görünüyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.