Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C语言中强制垃圾收集的最佳实践#_C#_.net_Garbage Collection - Fatal编程技术网

C# 在C语言中强制垃圾收集的最佳实践#

C# 在C语言中强制垃圾收集的最佳实践#,c#,.net,garbage-collection,C#,.net,Garbage Collection,根据我的经验,似乎大多数人都会告诉你,强制垃圾收集是不明智的,但在某些情况下,如果你处理的大型对象在0代中并不总是被收集,但内存是一个问题,那么强制收集可以吗?有这样做的最佳实践吗?我学会了不要试图比垃圾收集更聪明。尽管如此,在处理非托管资源(如文件I/O或数据库连接)时,我还是坚持使用关键字。不确定这是否是最佳做法,但在循环中处理大量图像时(即创建和处理大量图形/图像/位图对象),我定期让GC收集 我想我读到了GC只在程序(大部分)空闲的时候运行,而不是在一个密集循环的中间,所以它看起来像手动

根据我的经验,似乎大多数人都会告诉你,强制垃圾收集是不明智的,但在某些情况下,如果你处理的大型对象在0代中并不总是被收集,但内存是一个问题,那么强制收集可以吗?有这样做的最佳实践吗?

我学会了不要试图比垃圾收集更聪明。尽管如此,在处理非托管资源(如文件I/O或数据库连接)时,我还是坚持使用
关键字。

不确定这是否是最佳做法,但在循环中处理大量图像时(即创建和处理大量图形/图像/位图对象),我定期让GC收集


<>我想我读到了GC只在程序(大部分)空闲的时候运行,而不是在一个密集循环的中间,所以它看起来像手动GC有意义的区域。

我想你已经列出了最好的实践,除非真正需要,否则不使用它。我强烈建议您更详细地查看代码,如果需要首先回答这些问题,可以使用分析工具

  • 您的代码中是否有某些东西在比需要更大的范围内声明项
  • 内存使用率真的太高了吗
  • 比较使用GC.Collect()前后的性能,看看它是否真的有用

  • 最好的做法是不要强制进行垃圾收集

    根据MSDN:

    “强制垃圾回收是可能的 通过调用Collect收集,但是 大多数情况下,这应该是 避免,因为它可能会造成 性能问题。”

    但是,如果您能够可靠地测试代码,以确认调用Collect()不会产生负面影响,那么请继续

    当你不再需要物品时,尽量确保物品被清理干净。如果您有自定义对象,请查看如何使用“using语句”和IDisposable接口

    此链接提供了一些关于释放内存/垃圾收集等方面的实用建议:


    大型对象在LOH(大型对象堆)上分配,而不是在gen 0上。如果你是说他们没有用gen 0收集垃圾,你是对的。我相信它们只有在整个GC循环(第0、1和2代)发生时才会被收集

    也就是说,我相信在另一方面,当您处理大型对象时,GC会更积极地调整和收集内存,并且内存压力会增加


    很难说是否收集以及在什么情况下收集。我曾经在处理带有许多控件的对话框窗口/窗体等之后执行GC.Collect()(因为当窗体及其控件最终进入gen 2时,由于创建了许多业务对象实例/加载了大量数据-显然没有大型对象),但实际上这样做并没有在长期内注意到任何积极或消极的影响。

    假设您的程序没有内存泄漏,对象会累积,并且无法在Gen 0中进行GC加密,因为: 1) 它们被引用了很长时间,因此进入Gen1和Gen2; 2) 它们是大对象(>80K),所以进入LOH(大对象堆)。LOH不像Gen0、Gen1和Gen2那样进行压缩

    检查“.NET内存”的性能计数器,你会发现问题其实不是问题。通常,每10个Gen0 GC将触发1个Gen1 GC,每10个Gen1 GC将触发1个Gen2 GC。从理论上讲,如果GC0没有压力(如果程序内存使用真的是有线连接的话),GC1和GC2永远不会被GC-ed。我从来没有这样过


    对于问题2),您可以检查“.NET内存”性能计数器以验证LOH是否膨胀。如果这确实是您的问题所在,也许您可以按照本博客的建议创建一个大型对象池。

    还有一件事,显式触发GC Collect可能不会提高程序的性能。很有可能使情况变得更糟

    NET GC经过良好的设计和调整,具有自适应性,这意味着它可以根据程序内存使用的“习惯”调整GC0/1/2阈值。因此,它将在运行一段时间后适应您的程序。一旦显式调用GC.Collect,阈值将被重置!而.NET必须花时间再次适应您程序的“习惯”


    我的建议是永远信任.NETGC。如果出现任何内存问题,请检查“.NET内存”性能计数器并诊断我自己的代码。

    这样看-当垃圾桶的容量为10%时,扔掉厨房垃圾是更有效的方法,还是让垃圾桶装满后再取出

    如果不让垃圾填满,你就是在浪费时间,在外面的垃圾桶里走来走去。这类似于GC线程运行时发生的情况——所有托管线程在运行时都被挂起。如果我没有弄错的话,GC线程可以在多个AppDomain之间共享,因此垃圾收集会影响所有AppDomain

    当然,你可能会遇到这样一种情况,即如果你打算去度假,你很快就不会往垃圾桶里添加任何东西。那么,出门前把垃圾扔掉是个好主意

    这可能是强制GC有帮助的一次—如果您的程序空闲,则使用的内存不会被垃圾回收,因为没有分配

    但是,如果您能够可靠地测试代码,以确认调用Collect()不会产生负面影响,那么请继续

    IMHO,这类似于说“如果你能证明你的程序在将来永远不会有任何错误,那就继续吧…”


    严格来说,强制GC对于调试/测试非常有用。如果您觉得需要在其他任何时候这样做,那么要么是您弄错了,要么是您的程序构建错误。无论哪种方式,解决方案都不会强制GC…

    我认为下面给出的示例很好:
    class Program
    {    
        static void Main(string[] args)
            {
                SomePublisher publisher = new SomePublisher();
    
                for (int i = 0; i < 10; i++)
                {
                    SomeSubscriber subscriber = new SomeSubscriber(publisher);
                    subscriber = null;
                }
    
                GC.Collect();
                GC.WaitForPendingFinalizers();
    
                Console.WriteLine(SomeSubscriber.Count.ToString());
    
    
                Console.ReadLine();
            }
        }
    
        public class SomePublisher
        {
            public event EventHandler SomeEvent;
        }
    
        public class SomeSubscriber
        {
            public static int Count;
    
            public SomeSubscriber(SomePublisher publisher)
            {
                publisher.SomeEvent += new EventHandler(publisher_SomeEvent);
            }
    
            ~SomeSubscriber()
            {
                SomeSubscriber.Count++;
            }
    
            private void publisher_SomeEvent(object sender, EventArgs e)
            {
                // TODO: something
                string stub = "";
            }
        }