driveinfo 不适合高频轮询,因其每次实例化均触发底层 i/o 查询(如 getdiskfreespaceex),间隔过短易致值跳变或异常;建议轮询周期不小于 3–5 秒,复用缓存实例并注意线程安全。

DriveInfo.GetDrives() 能列出所有盘符,但别直接用它查剩余空间
因为 DriveInfo.GetDrives() 返回的是未初始化的驱动器对象,调用 AvailableFreeSpace 或 TotalFreeSpace 前必须先确保驱动器就绪(比如不是光驱空仓、网络驱动器离线、U 盘被拔出)。否则会抛出 IOException 或 UnauthorizedAccessException。
实操建议:
- 始终用
try/catch包裹对AvailableFreeSpace的访问,而不是依赖IsReady判断——某些情况下IsReady == true但后续读取仍失败 - 优先用
TotalFreeSpace(含系统保留空间)而非AvailableFreeSpace(仅当前用户可用),监控告警场景下后者容易误判 - 避免在 UI 线程频繁轮询,尤其是遍历所有驱动器时,
DriveInfo构造本身有 I/O 开销
监控磁盘容量时,为什么 DriveInfo 不适合高频轮询
DriveInfo 每次实例化都会触发一次底层 WMI 或 Win32 API 查询,Windows 下实际调用的是 GetDiskFreeSpaceEx。连续调用间隔小于 500ms 时,可能因系统缓存未更新或句柄竞争导致值跳变甚至异常。
实操建议:
- 轮询周期不低于 3–5 秒;若需实时响应(如写入前检查),改用单次查询 + 业务逻辑兜底(例如写入失败后重查)
- 不要为每个盘符新建
DriveInfo实例反复查,缓存实例并复用(注意:DriveInfo不是线程安全的,多线程读需加锁或用ThreadLocal<driveinfo></driveinfo>) - 想避开 .NET 封装开销?可 P/Invoke
GetDiskFreeSpaceEx,参数是string lpRootPathName,返回long*类型的可用字节数,比DriveInfo快约 30%~40%
“C:” 盘显示剩余 0 字节?可能是权限或符号链接导致
常见错误现象:new DriveInfo("C:\").AvailableFreeSpace 返回 0,但资源管理器显示还有几十 GB。这通常不是磁盘真满了,而是当前进程无权读取卷标信息,或 C: 是重定向到另一物理卷(如 WSL2 的 \wsl$distro 挂载点)。
实操建议:
- 确认进程是否以管理员权限运行(尤其在 Server 系统或启用了 UAC 的机器上)
- 检查路径是否为真实本地路径:用
Path.IsPathRooted()和DriveInfo.GetDrives().Any(d => d.Name == "C:\")双重验证 - 遇到
UnauthorizedAccessException时,跳过该驱动器记录日志,不要 throw —— 监控服务应容忍部分盘符不可读 - WSL2、Docker Desktop 虚拟磁盘等场景下,
DriveInfo对\wsl$或\docker-desktop-data根本不识别,需单独处理
获取剩余空间后,单位换算和显示要注意什么
.NET 返回的 AvailableFreeSpace 是字节(long),直接除以 1024³ 得 GiB 容易丢失精度,且 Windows 资源管理器用的是二进制前缀(GiB),而有些旧工具用十进制(GB),混用会导致显示偏差 7% 左右。
实操建议:
- 统一用二进制单位:1 KiB = 1024, 1 MiB = 1024², 1 GiB = 1024³
- 格式化时保留一位小数,用
Math.Round(bytes / Math.Pow(1024, n), 1),别用字符串截断 - 警惕
int溢出:32 位整数最大约 2GiB,而现代硬盘动辄 TB 级,务必全程用long运算 - 显示给用户看时,加上单位缩写(如 “24.6 GiB”),避免只写数字——没人记得清 26382947123 是多少 GB
DriveInfo 底层其实很“脆弱”。










