C# GC经常触发这种情况是正常的吗?

C# GC经常触发这种情况是正常的吗?,c#,garbage-collection,C#,Garbage Collection,今天我注意到,我制作的一个小程序在程序生命周期的前10~20秒内经常触发GC。之后,它几乎再也不会触发。 在这段时间内,只有1个函数运行,如下所示。获取约2k个文件路径,并过滤掉其中的大部分 public static string[] FilterFiles(string path) { // Fetch the files from given directory var files = Directory.GetFiles(path);

今天我注意到,我制作的一个小程序在程序生命周期的前10~20秒内经常触发GC。之后,它几乎再也不会触发。

在这段时间内,只有1个函数运行,如下所示。获取约2k个文件路径,并过滤掉其中的大部分

 public static string[] FilterFiles(string path)
    {
        // Fetch the files from given directory
        var files = Directory.GetFiles(path);

        // Delete all files that are to small
        foreach (string file in files)
        {
            string fullFile = default(string);

            try
            {
                fullFile = File.ReadAllText(file);
            }
            catch
            {
                continue;
            }

            if (fullFile.Length < Settings.MinimumFileSize)
            {
                File.Delete(file);
            }
        }

        // Obtain the new list without the small files
        List<string> cleanFiles = new List<string>(Directory.GetFiles(path));
        List<string> cleanReturn = new List<string>(Directory.GetFiles(path));

        // Remove files we have handled before
        foreach (string file in cleanFiles)
        {
            if (File.Exists(Settings.ExtractFolder + "\\" + file.Substring(file.LastIndexOf('\\') + 1) + "_Extract.xml"))
            {
                cleanReturn.Remove(file);
            }
        }

        return cleanReturn.ToArray();
    }
公共静态字符串[]过滤器文件(字符串路径)
{
//从给定目录获取文件
var files=Directory.GetFiles(路径);
//删除所有太小的文件
foreach(文件中的字符串文件)
{
string fullFile=默认值(字符串);
尝试
{
fullFile=File.ReadAllText(文件);
}
抓住
{
继续;
}
if(fullFile.Length

GC在这段时间内经常触发这种情况正常吗?

嗯,是的。您正在创建大量生命周期很短的对象,这些对象将尽快被处理

尽量不要读取整个文件。相反,只是

这里您将枚举目录列表两次,这也是不必要的:

List<string> cleanFiles = new List<string>(Directory.GetFiles(path));
List<string> cleanReturn = new List<string>(Directory.GetFiles(path));

在那里使用
StringBuilder
string.Format
,并尽可能多地在前面执行操作。

您真的不需要读取整个文件来查找其长度。只需执行:
long length=newfileinfo(file).length

通过使用
目录。EnumerateFiles(path)
,也可以枚举文件,而无需将所有文件名读入数组

我想你可以这样重写你的整个函数:

public static IEnumerable<string> FilterFiles(string path)
{
    foreach (string file in Directory.EnumerateFiles(path))
    {
        if (new FileInfo(file).Length < Settings.MinimumFileSize)
            File.Delete(file);
        else if (!File.Exists(Settings.ExtractFolder + "\\" + file.Substring(file.LastIndexOf('\\') + 1) + "_Extract.xml"))
            yield return file;
    }
}
或者,如果要在应用其余逻辑之前强制删除所有小文件,请先使用
ToArray()
,然后再使用
foreach

foreach (string file in FilterFiles(myPath).ToArray())
    ...

但是要回答你的问题:是的,如果你创建了很多小对象,GC可能会经常运行。如果您创建了一些大字符串,它将特别运行:您正在读取到内存中的文件有多大?

这会导致性能下降吗?您正在操作的字符串有多长?@dotctor强制关闭gc可节省约2秒。所以是的。@Theodoroschatzigannakis文件路径,<100个字符不读取整个文件,但使用文件信息将其减少到仅3个GC。谢谢
foreach (string file in FilterFiles(myPath))
    ...
foreach (string file in FilterFiles(myPath).ToArray())
    ...