为何Windows上C#异步IO同步执行?与.NET文档不符原因探究
.NET异步文件IO在Windows下的并行执行异常问题
根据.NET文档说明,异步IO命令可用于并行执行文件操作,但实际测试发现Windows平台下存在不符合预期的行为:
测试代码
public static async Task SimpleParallelWriteByteAsync() { var rootFilePath = "C:/temp/asynctest2"; var fileSize = 1024 * 1024 * 100; if (Directory.Exists(rootFilePath)) Directory.Delete(rootFilePath, true); Directory.CreateDirectory(rootFilePath); var buffer = new byte[fileSize]; new Random().NextBytes(buffer); IList<Task> writeTaskList = new List<Task>(); Stopwatch sw = Stopwatch.StartNew(); for (int index = 0; index <= 10; index += 1) { string fileName = $"file-{index:00}.txt"; string filePath = Path.Combine(rootFilePath, fileName); writeTaskList.Add(File.WriteAllBytesAsync(filePath, buffer)); } var timespanLoop = sw.Elapsed; await Task.WhenAll(writeTaskList); var timespanAfterWhenall = sw.Elapsed; Console.WriteLine($"loop {timespanLoop} after when all {timespanAfterWhenall}"); }
Windows平台测试结果
运行后输出:
loop 00:00:05.6234609 after when all 00:00:05.6254815
两个时间值差异极小,说明循环过程中异步写入实际是串行执行的。这一现象在本地SSD、网络驱动器,以及net472、net6.0、net8.0环境中均可复现。
修改代码后的结果
将添加任务的代码改为:
writeTaskList.Add(Task.Run(() => File.WriteAllBytesAsync(filePath, buffer)));
执行后得到预期的并行输出:
loop 00:00:00.0089046 after when all 00:00:01.2339927
Linux平台测试结果
在Linux上,原异步代码可正常并行执行,输出示例:
00:00:00.0082008 after when all 00:00:03.0910144
疑问
- 是什么机制控制了Windows平台下的这一行为?
- 为何.NET文档的描述与实际行为存在差异?
按照异步IO的设计原理,异步文件操作无需占用线程,只需向操作系统发送异步写入请求,待操作完成后由操作系统通知.NET即可。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

