System.IO.Compression和异步I/O中的ZipFile和ZipArchive类

本文关键字:ZipFile 中的 ZipArchive IO Compression 异步 System | 更新日期: 2023-09-27 18:06:21

.NET4.5添加了新的类来使用zip归档。现在你可以做这样的事情:

using (ZipArchive archive = ZipFile.OpenRead(zipFilePath))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        // Extract it to the file
        entry.ExtractToFile(entry.Name);
        // or do whatever you want
        using (Stream stream = entry.Open())
        {
            ...
        }
    }
}

显然,如果您使用大型归档,从归档中读取文件可能需要几秒钟甚至几分钟的时间。所以,如果你正在编写一些GUI应用程序(WinForms或WPF(,你可能会在一个单独的线程中运行这样的代码,否则你会阻塞UI线程,让你的应用程序用户非常不安。

然而,该代码中的所有I/O操作都将在2016年被认为"不酷"的阻塞模式下执行。所以有两个问题:

  1. 是否可以使用System.IO.Compression类(或者其他第三方.NET库(获得异步I/O
  2. 这样做有意义吗?我的意思是,压缩/提取算法无论如何都非常消耗CPU,所以如果我们甚至从
  3. CPU绑定的阻塞I/O切换到异步I/O,性能增益可能相对较小(当然是百分比,而不是绝对值(

更新:

对于彼得·杜尼霍的回答:是的,你是对的。出于某种原因,我没有考虑这个选项:

using (Stream zipStream = entry.Open())
using (FileStream fileStream = new FileStream(...))
{
    await zipStream.CopyToAsync(fileStream);
}

这绝对有效。谢谢

顺便说一下

await Task.Run(() => entry.ExtractToFile(entry.Name));

将仍然

是CPU绑定的阻塞I/O操作,只是在单独的线程中在I/O操作期间消耗线程池中的线程。

然而,正如我所看到的,.NET的开发人员仍然对一些归档操作使用阻塞I/O(比如这段代码来枚举归档中的条目,例如:ZipArchive.cs ondotnet@github)。我还发现了一个悬而未决的问题,即ZipFileAPI缺乏异步API。

我想现在我们有部分异步支持,但还远远不够完整。

System.IO.Compression和异步I/O中的ZipFile和ZipArchive类

  1. 是否可以使用System.IO.Compression类(或者其他第三方.NET库(获得异步I/O

根据"异步I/O"的实际含义,您可以使用内置的.NET类型来实现。例如:

using (ZipArchive archive = await Task.Run(() => ZipFile.OpenRead(zipFilePath)))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        // Extract it to the file
        await Task.Run(() => entry.ExtractToFile(entry.Name));
        // or do whatever you want
        using (Stream stream = entry.Open())
        {
            // use XXXAsync() methods on Stream object
            ...
        }
    }
}

如果您愿意,可以将这些封装在XXXAsync()扩展方法中。

  1. 这样做有意义吗?我的意思是,压缩/提取算法无论如何都非常消耗CPU,所以如果我们甚至从CPU绑定I/O切换到异步I/O,性能增益可能相对较小(当然是百分比,而不是绝对值(

至少有三个理由:

  1. CPU速度非常快。在许多情况下,I/O仍然是瓶颈,因此异步等待I/O非常有用
  2. 多核CPU是常态。因此,让一个核心进行解压缩,而另一个核心做其他工作是有用的
  3. 异步操作并不完全与性能有关,在某些情况下甚至根本与性能无关。异步处理存档允许用户界面保持响应,这很有用