.NET中如何异步获取文件属性(大小、创建时间、修改时间等)
在.NET中异步获取文件属性的可行方案
1. 基于.NET 6+的原生异步API(优先推荐)
从.NET 6开始,框架提供了原生的异步文件属性获取能力,完全适配高并发场景:
- 使用
FileSystemInfo.RefreshAsyncFileInfo的父类FileSystemInfo新增了异步刷新方法,异步加载最新文件属性后,即可同步访问LastWriteTime、CreationTime等元数据:var fileInfo = new FileInfo("target-file.txt"); await fileInfo.RefreshAsync(); var lastWriteTime = fileInfo.LastWriteTimeUtc; - 使用
File类的静态异步方法
框架还为File类提供了直接获取单个属性的异步方法,无需创建FileInfo实例,代码更轻量化:
这些方法内部已优化并发逻辑,不会造成大量线程阻塞。// 获取创建时间 var creationTime = await File.GetCreationTimeUtcAsync("target-file.txt"); // 获取最后写入时间 var lastWriteTime = await File.GetLastWriteTimeUtcAsync("target-file.txt"); // 获取最后访问时间 var lastAccessTime = await File.GetLastAccessTimeUtcAsync("target-file.txt");
2. P/Invoke调用系统API(旧版本.NET备选)
如果使用.NET 6之前的版本,可以通过P/Invoke调用Windows系统API,结合线程池实现伪异步(避免阻塞主线程),或者使用重叠IO实现真正的异步IO(复杂度较高)。以下是简化版的伪异步实现示例:
using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Threading.Tasks; public static class AsyncFileAttributeHelper { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool GetFileAttributesEx(string lpFileName, int fInfoLevelId, out WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); private const int GetFileExInfoStandard = 0; [StructLayout(LayoutKind.Sequential)] private struct WIN32_FILE_ATTRIBUTE_DATA { public uint dwFileAttributes; public FILETIME ftCreationTime; public FILETIME ftLastAccessTime; public FILETIME ftLastWriteTime; public uint nFileSizeHigh; public uint nFileSizeLow; } [StructLayout(LayoutKind.Sequential)] private struct FILETIME { public uint dwLowDateTime; public uint dwHighDateTime; } public static Task<DateTime> GetLastWriteTimeUtcAsync(string filePath) { return Task.Run(() => { if (!GetFileAttributesEx(filePath, GetFileExInfoStandard, out var data)) throw new Win32Exception(); long fileTimeTicks = ((long)data.ftLastWriteTime.dwHighDateTime << 32) | data.ftLastWriteTime.dwLowDateTime; return DateTime.FromFileTimeUtc(fileTimeTicks); }); } }
总结
优先选择.NET 6+提供的原生异步API,这些方案经过官方优化,适配高并发场景且实现简单。仅在旧版本.NET环境下,才考虑P/Invoke方案。
内容的提问来源于stack exchange,提问作者Drew Noakes
相关产品推荐
相关产品推荐

