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

为何带Task.Run的ReadAllBytesAsync多文件读取比无Task.Run版本快近一倍?

为什么带Task.Run的ReadAllBytesAsync版本比直接调用快近一倍?

我尝试用File.ReadAllBytesAsync读取两个100MB的二进制文件(test2.bin是test1.bin的副本),发现带Task.Run的ReadAll2方法比直接调用的ReadAll1快近一倍,原本以为两者效果相当。性能测试数据如下:

方法平均值误差标准差内存分配
ReadAll181.57 ms1.385 ms1.942 ms199.37 MB
ReadAll244.55 ms1.041 ms3.021 ms199.37 MB

对应的测试代码:

public static async Task ReadAll1()
{
    var tasks = new List<Task>();
    tasks.Add(File.ReadAllBytesAsync(@"test1.bin"));
    tasks.Add(File.ReadAllBytesAsync(@"test2.bin"));
    await Task.WhenAll(tasks);
}
public static async Task ReadAll2()
{
    var tasks = new List<Task>();
    tasks.Add(Task.Run(() => File.ReadAllBytesAsync(@"test1.bin")));
    tasks.Add(Task.Run(() => File.ReadAllBytesAsync(@"test2.bin")));
    await Task.WhenAll(tasks);
}

核心原因在于File.ReadAllBytesAsync的同步前置操作并行化:

  • File.ReadAllBytesAsync虽是异步IO方法,但它的初始阶段(打开文件、校验权限、初始化文件流等)是同步执行的,这部分操作会占用当前线程直到完成。
  • 在ReadAll1中,两个ReadAllBytesAsync在同一个线程上依次启动,导致两个文件的打开操作串行执行——第一个文件打开完成后才会启动第二个文件的打开流程,后续的异步读取也因此延迟,总耗时接近两次读取的时间之和。
  • 在ReadAll2中,Task.Run将每个ReadAllBytesAsync的启动(包括同步的打开阶段)放到独立的线程池线程上执行,两个文件的打开和读取操作可以真正并行启动,总耗时接近单次文件读取的时间,因此速度快了近一倍。

补充说明:这种差异在文件较大时更明显,因为同步前置操作的时间占比相对读取本身的耗时更小,并行启动后整体效率提升更显著。两个方法的内存分配一致,说明最终的读取逻辑没有区别,差异仅来自任务启动阶段的并行度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:23:31