You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#开发文件管理器时如何优化目录内容读取速度

优化方案与编码规范说明

核心性能问题根源

当前代码最大的性能损耗来自4次重复遍历磁盘目录:两次调用Directory.GetDirectories、两次调用Directory.GetFiles,每次调用都会触发磁盘IO操作,目录内条目越多,重复开销越大。其次是UI频繁重绘、图标重复加载、重复计算属性的额外开销。

具体优化措施

  • 减少磁盘IO次数:仅遍历1次目录,同时读取所有文件/文件夹的元信息缓存到内存,后续计算列宽、生成列表项都直接用缓存数据,避免重复访问磁盘。
  • 禁用UI临时重绘:ListView批量添加项前调用BeginUpdate()暂停重绘,所有项添加完成后调用EndUpdate()一次性刷新,大幅降低UI渲染开销。
  • 添加图标缓存:文件夹图标全局只加载1次,相同后缀的文件图标只提取1次,用字典存储后缀与图标索引的映射,避免重复读取图标资源。
  • 复用计算结果:第一次处理路径时就调用系统APIPath.GetFileName()获取文件名、计算长度、获取文件类型,后续直接复用结果,避免重复字符串操作和重复调用GetFileType。
  • 使用枚举API替代全量读取:用Directory.EnumerateDirectories和Directory.EnumerateFiles替代Get系列API,大目录下可以边遍历边处理,不需要等待全量路径读取完成。

编码规范优化点

  • 路径处理优先使用System.IO.Path下的系统API,不要手动切割字符串,避免边界错误和平台兼容性问题。
  • 路径拼接使用Path.Combine(),不要直接拼接字符串,避免斜杠重复或缺失的问题。
  • 访问文件/目录时添加必要的异常捕获,处理无权限、路径不存在等边界情况,避免程序直接崩溃。
  • 避免硬编码常量,比如字符宽度系数、固定图标路径,可以抽成常量方便后续统一修改。

优化后参考代码

// 提前定义全局图标缓存,放在类成员位置,不要每次调用都初始化
private readonly Dictionary<string, int> _iconCache = new Dictionary<string, int>();
private const int CharWidthCoefficient = 8;
private const int DateColumnWidth = 160;

private void GetDirectoryContent(string directory)
{
    txtPath.Text = directory;
    currentDirectoryFiles.Clear();
    filesList.Items.Clear();
    smallImageList.Images.Clear();
    _iconCache.Clear();

    // 预添加文件夹图标,所有文件夹复用这一个
    var folderIconPath = Path.Combine(Environment.CurrentDirectory, "Xplorer.ico");
    smallImageList.Images.Add(new Bitmap(folderIconPath));
    const int folderIconIndex = 0;
    _iconCache.Add("Folder", folderIconIndex);

    int longestName = 0;
    int longestType = 0;
    // 缓存所有目录项信息,只遍历1次磁盘
    var dirItems = new List<(string FullPath, string Name, DateTime LastWriteTime, string Type, int IconIndex)>();

    // 处理文件夹
    foreach (string dirPath in Directory.EnumerateDirectories(directory))
    {
        try
        {
            string name = Path.GetFileName(dirPath);
            string type = "Folder";
            int iconIndex = _iconCache[type];
            
            if (name.Length > longestName) longestName = name.Length;
            if (type.Length > longestType) longestType = type.Length;

            dirItems.Add((dirPath, name, Directory.GetLastWriteTime(dirPath), type, iconIndex));
        }
        catch (UnauthorizedAccessException)
        {
            // 跳过无权限访问的目录,可根据需求添加提示
            continue;
        }
    }

    // 处理文件
    foreach (string filePath in Directory.EnumerateFiles(directory))
    {
        try
        {
            string name = Path.GetFileName(filePath);
            string ext = Path.GetExtension(filePath).ToLower();
            string type = GetFileType(filePath);
            
            // 缓存同后缀文件图标
            if (!_iconCache.ContainsKey(ext))
            {
                var icon = Icon.ExtractAssociatedIcon(filePath);
                smallImageList.Images.Add(icon ?? throw new InvalidOperationException());
                _iconCache.Add(ext, smallImageList.Images.Count - 1);
            }
            int iconIndex = _iconCache[ext];

            if (name.Length > longestName) longestName = name.Length;
            if (type.Length > longestType) longestType = type.Length;

            dirItems.Add((filePath, name, File.GetLastWriteTime(filePath), type, iconIndex));
        }
        catch (UnauthorizedAccessException)
        {
            // 跳过无权限访问的文件
            continue;
        }
    }

    // 配置ListView列
    filesList.Sorting = SortOrder.Ascending;
    filesList.View = View.Details;
    filesList.Columns.Clear();
    filesList.Columns.Add("Name", longestName * CharWidthCoefficient);
    filesList.Columns.Add("Date Modified", DateColumnWidth);
    filesList.Columns.Add("Type", longestType * CharWidthCoefficient);

    // 批量添加项,暂停UI重绘
    filesList.BeginUpdate();
    foreach (var item in dirItems)
    {
        ListViewItem row = new ListViewItem(item.Name, item.IconIndex);
        row.SubItems.Add(item.LastWriteTime.ToString(CultureInfo.CurrentCulture));
        row.SubItems.Add(item.Type);
        row.Tag = item.Type == "Folder" ? "Folder" : "File";
        currentDirectoryFiles.Add(item.FullPath);
        filesList.Items.Add(row);
    }
    filesList.EndUpdate();
}

内容的提问来源于stack exchange,提问作者user11423796

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 17:06:04