0

0

C#异步枚举文件 C#如何使用Directory.EnumerateFiles进行高效遍历

星降

星降

发布时间:2026-02-15 09:40:54

|

388人浏览过

|

来源于php中文网

原创

directory.enumeratefiles 因返回 ienumerable、按需枚举文件路径,避免内存溢出,适合大目录过滤与提前终止;但为同步 i/o,非真正异步,需配合 task.run 或手动实现异步流。

c#异步枚举文件 c#如何使用directory.enumeratefiles进行高效遍历

Directory.EnumerateFiles 为什么比 GetFiles 更适合大目录

它返回 IEnumerable<string></string> 而非一次性加载全部路径到内存,遍历时按需获取文件名,避免在含数万文件的目录中触发 OutOfMemoryException。尤其适合后续要过滤、投影或提前中断的场景。

但注意:枚举本身仍是同步 I/O,不等于“异步遍历”——它不会释放当前线程。真需要非阻塞,得配合 Task.Run 或用 FileSystemWatcher + 异步回调组合实现。

  • 不要在 UI 线程直接调用它处理超大目录,否则界面卡死
  • 路径通配符(如 "*.log")由 Windows API 原生支持,效率高;正则过滤必须靠 C# 侧 .Where(),会遍历全部再筛选
  • 若需访问文件属性(大小、时间戳),EnumerateFiles 只返回路径,额外 FileInfo 构造会引发重复系统调用——此时应改用 EnumerateFileSystemEntries 配合 new FileInfo() 批量缓存

如何安全处理权限不足或路径不存在的异常

Directory.EnumerateFiles 在遇到拒绝访问(UnauthorizedAccessException)或路径不存在(DirectoryNotFoundException)时直接抛异常,不跳过。无法像 PowerShell 的 Get-ChildItem -ErrorAction SilentlyContinue 那样静默忽略。

常见做法是封装一层可恢复的枚举器:

Trickle AI
Trickle AI

多功能零代码AI应用开发平台

下载
public static IEnumerable<string> SafeEnumerateFiles(string path, string searchPattern = "*.*", SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
    try
    {
        return Directory.EnumerateFiles(path, searchPattern, searchOption);
    }
    catch (UnauthorizedAccessException)
    {
        yield break;
    }
    catch (DirectoryNotFoundException)
    {
        yield break;
    }
}
  • 不能用 try/catch 包裹整个 foreach 循环——异常发生在 MoveNext() 内部,循环外捕获不到
  • 子目录递归时,某一级失败会导致整个枚举终止;如需继续遍历兄弟目录,得手动实现目录树迭代(用 EnumerateDirectories + 逐层 EnumerateFiles
  • 某些网络路径(如断开的 NAS)可能抛 IOException,建议一并 catch

配合 LINQ 实现延迟过滤与提前退出

利用其返回 IEnumerable 的特性,把耗时操作(如正则匹配、字符串处理)和终止条件(如只取前 100 个)留在枚举过程中,避免无谓遍历:

var recentLogs = Directory.EnumerateFiles(@"C:\App\Logs", "*.log", SearchOption.AllDirectories)
    .Where(p => File.GetLastWriteTime(p) > DateTime.Now.AddDays(-7))
    .Take(100)
    .ToArray(); // 此时才真正触发遍历
  • Take(n) 后接 ToArray()ToList() 是触发执行的关键,纯链式调用不干活
  • File.GetLastWriteTime(p) 是同步磁盘 I/O,每调一次都可能慢;如果只是按名称过滤,优先用 searchPattern 参数(如 "error_*.log")交由系统完成
  • 不要在 Where 中做复杂解析(如读文件头),那会把延迟优势完全抵消

想真正异步?得绕开 EnumerateFiles 自己调度

Directory.EnumerateFiles 没有异步重载,.NET 6+ 的 FileSystemEnumerable 也未暴露异步接口。所谓“异步枚举文件”,本质是把同步枚举扔进线程池:

var files = await Task.Run(() =>
    Directory.EnumerateFiles(@"D:\Data", "*.csv")
        .Where(f => f.Length > 1000)
        .Take(50)
        .ToArray());
  • 这能释放调用线程(比如 ASP.NET Core 的请求线程),但**不减少总耗时,也不降低 I/O 压力**
  • 高频调用时注意线程池饥饿——大量 Task.Run 可能挤占 CPU 密集型任务资源
  • 若目标是响应式流(如 Web API 分块返回文件列表),应考虑用 IAsyncEnumerable<string></string> 手动包装,每次 yield return 前加 await Task.Yield() 让出控制权

真正的异步文件系统操作仍受限于 Windows API 和底层驱动,目前没有银弹。别被“异步枚举”字面误导——先厘清你要解的是阻塞问题,还是吞吐瓶颈,或是 UI 响应性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

162

2025.12.04

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

551

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

214

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1552

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

640

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

905

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

856

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

185

2025.07.29

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

76

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.5万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号