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

Ale*_*tev 3 .net c# io asynchronous system.io.compression

.NET 4.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())
        {
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,如果您使用大型存档,则可能需要几秒甚至几分钟才能从存档中读取文件.因此,如果您正在编写一些GUI应用程序(WinForms或WPF),您可能会在单独的线程中运行此类代码,否则您将阻止UI线程并使您的应用程序用户非常沮丧.

但是,此代码中的所有I/O操作都将在2016年被视为"不酷" 的阻塞模式下执行.因此,有两个问题:

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

更新:

回答Peter Duniho的回答:是的,你是对的.出于某种原因,我没有考虑这个选项:

using (Stream zipStream = entry.Open())
using (FileStream fileStream = new FileStream(...))
{
    await zipStream.CopyToAsync(fileStream);
}
Run Code Online (Sandbox Code Playgroud)

绝对有效.谢谢!

顺便说说

await Task.Run(() => entry.ExtractToFile(entry.Name));
Run Code Online (Sandbox Code Playgroud)

还会 是CPU限制的阻塞I/O操作,只是在单独的线程中 在I/O操作期间消耗线程池中的线程.

但是,我可以看到.NET的开发人员仍然使用阻塞I/O进行某些归档操作(例如,此代码枚举归档中的条目,例如:dotnet @ github上的ZipArchive.cs).我还发现了一个关于ZipFile API缺少异步API的公开问题.

我猜这时我们有部分异步支持,但还远未完成.

Pet*_*iho 6

  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
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

XXXAsync()如果您愿意,可以在扩展方法中包装它们.

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

至少有三个理由:

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