Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.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# GC.Collect()和GC.Collect(GC.MaxGeneration)之间有什么区别?_C#_.net_Garbage Collection - Fatal编程技术网

C# GC.Collect()和GC.Collect(GC.MaxGeneration)之间有什么区别?

C# GC.Collect()和GC.Collect(GC.MaxGeneration)之间有什么区别?,c#,.net,garbage-collection,C#,.net,Garbage Collection,我见过多个Anwser,建议运行GC.Collect(GC.MaxGeneration) 由于方法GC.Collect()将收集所有现有的代,两者之间有什么区别吗 也许如果只有两代而不是三代存活,GC将收集两代,而不会尝试收集第三代,这将提高性能。但是说真的,这有意义吗?唯一的区别是GC.Collect()将使用而GC.Collect(GC.MaxGeneration)将使用GCCollectionMode.Default(至少在.NET Framework 4.5中)。还有一些重载,您可以在其

我见过多个Anwser,建议运行
GC.Collect(GC.MaxGeneration)

由于方法
GC.Collect()
将收集所有现有的代,两者之间有什么区别吗


也许如果只有两代而不是三代存活,GC将收集两代,而不会尝试收集第三代,这将提高性能。但是说真的,这有意义吗?

唯一的区别是
GC.Collect()
将使用而
GC.Collect(GC.MaxGeneration)
将使用
GCCollectionMode.Default
(至少在.NET Framework 4.5中)。还有一些重载,您可以在其中手动指定收集模式

/// <summary>Specifies the behavior for a forced garbage collection.</summary>
public enum GCCollectionMode
{
    /// <summary>The default setting for this enumeration, which is currently <see cref="F:System.GCCollectionMode.Forced" />. </summary>
    Default,
    /// <summary>Forces the garbage collection to occur immediately.</summary>
    Forced,
    /// <summary>Allows the garbage collector to determine whether the current time is optimal to reclaim objects. </summary>
    Optimized
}
///指定强制垃圾回收的行为。
公共枚举GCCollectionMode
{
///此枚举的默认设置,当前为。
违约
///强制立即进行垃圾收集。
强迫,
///允许垃圾收集器确定当前时间是否是回收对象的最佳时间。
优化
}
GC.Collect()
使用
GCCollectionMode.Default
GC.Collect(GC.MaxGeneration)

所以,两者之间没有区别!
根据MSDN

GCCollectionMode枚举

默认值:此枚举的默认设置,即 当前强制。
强制:强制垃圾收集 立即发生。
优化:允许垃圾 收集器以确定当前时间是否是回收的最佳时间 对象

使用反射器:

[MethodImpl(MethodImplOptions.InternalCall)]
private static void nativeCollectGeneration(int generation, int mode); 

public static void Collect()
{
  GC.nativeCollectGeneration(-1, 0);
}

public static void Collect(int generation)
{
  GC.Collect(generation, GCCollectionMode.Default);
}
p.S.
0
GCCollectionMode。默认值相同。

GC.Collect()可能不起任何作用,因为它对GCCollectionMode使用了“优化的”

MSDN on Optimized->允许垃圾收集器确定当前时间是否是回收对象的最佳时间

GC.Collect(GC.MaxGeneration)对GCCollectionMode使用“强制”

MSDN on Forced->强制立即进行垃圾收集


两者都将尝试为所有代进行回收。

标准(系统启动)垃圾收集的行为如下:

  • 从GenX中删除所有非根目录项(即从活动代码中引用的项)
  • 将所有剩余项目从GenX升级到GenX+1
  • 如果GenX+1中没有足够的空间容纳新项目,请对GenX+1重复上述步骤
  • 因此,标准集合可能只收集Gen0,并将一些数据混洗到Gen1中,然后停止。这有助于延长到达Gen2的对象的使用寿命:Gen2的收集频率远低于Gen0,因此到达Gen2的对象可能会挂起一段时间

    如果强制收集所有代,则会立即收集Gen2中的对象。这将释放更多内存,但也会对性能产生影响


    最重要的是,任何收藏品都将向下一代推广扎根产品。这是手动收集不好的一个原因:项目将不必要地升级到Gen1/2,然后实际上会停留更长时间(除非您反复使用手动GC,这只会加剧问题…。

    以下是GC类的内部代码

    // Forces a collection of all generations from 0 through Generation.
    //
    public static void Collect(int generation) {
        Collect(generation, GCCollectionMode.Default);
        }
    
    // Garbage Collect all generations.
    //
    [System.Security.SecuritySafeCritical]  // auto-generated
    public static void Collect() {
        //-1 says to GC all generations.
        _Collect(-1, (int)GCCollectionMode.Default);
    }
    
    [System.Security.SecuritySafeCritical]  // auto-generated
    public static void Collect(int generation, GCCollectionMode mode)
    {
        if (generation<0)
        {
            throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
        }
        if ((mode < GCCollectionMode.Default) || (mode > GCCollectionMode.Optimized))
        {
            throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_Enum"));
        }
        Contract.EndContractBlock();
        _Collect(generation, (int)mode);
    }
    
    //强制收集从0到生成的所有代。
    //
    公共静态void Collect(int生成){
    收集(生成,GCCollectionMode.Default);
    }
    //垃圾代代相传。
    //
    [System.Security.SecuritySafeCritical]//自动生成
    公共静态void Collect(){
    //-1对每一代人来说都是如此。
    _Collect(-1,(int)GCCollectionMode.Default);
    }
    [System.Security.SecuritySafeCritical]//自动生成
    公共静态void Collect(int生成,GCCollectionMode)
    {
    if(生成GCCollectionMode.Optimized))
    {
    抛出新ArgumentOutOfRangeException(Environment.GetResourceString(“ArgumentOutOfRange_Enum”);
    }
    Contract.EndContractBlock();
    _收集(生成,(int)模式);
    }
    

    在这里,您可以看到两个方法都使用两个参数调用Collect方法。收集(整数生成,GCCollectionMode模式)

    你确定他们使用不同的模式吗?我认为它们都使用默认+阻塞。GC.Collect()使用默认模式。您可以使用ilspy/etc进行检查。似乎唯一的区别是_Collect(GC.MaxGeneration,0)与_Collection(-1,0)。@CodesInChaos-是的,只查看了ilspy中的源代码。也许您也可以将其链接起来。在不同的.NET framework版本中使用的枚举值似乎有所不同。。。您查看了哪个.NET framework版本?值得注意的是,自上一个Gen1集合以来未写入的Gen1或Gen2中的对象不能包含Gen0中的任何对象,因此在Gen0集合期间可以完全忽略。同样,自上一个Gen2集合以来未写入的Gen2中的对象不能包含Gen0或Gen1中的任何对象,并且在Gen0或Gen1集合期间可以完全忽略该对象。利用尚未编写的Gen1和Gen2对象不需要检查这一事实的能力是分代GC性能的最大关键。