.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())
{
...
}
}
}
明らかに、大きなアーカイブを扱う場合、アーカイブからファイルを読み取るのに数秒または数分かかる場合があります。そのため、GUI アプリ (WinForms または WPF) を作成している場合、おそらくそのようなコードを別のスレッドで実行するでしょう。そうしないと、UI スレッドがブロックされ、アプリのユーザーが非常に動揺します。
ただし、このコードのすべての I/O 操作は、2016 年に「クールではない」と見なされるブロッキング モードで実行されます。したがって、2 つの質問があります。
- クラス (または他のサードパーティの .NET ライブラリ)で非同期 I/O を取得することは可能
System.IO.Compression
ですか? - それをするのは理にかなっていますか?とにかく、圧縮/抽出アルゴリズムは非常にCPUを消費するということです。
CPU バウンドI/O を非同期 I/O にブロックすると、パフォーマンスの向上は比較的小さくなります (もちろん、絶対値ではなくパーセンテージで)。
アップデート:
Peter Duniho からの回答に返信するには: はい、その通りです。何らかの理由で、私はこのオプションについて考えていませんでした:
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 を使用しています (たとえば、アーカイブ内のエントリを列挙するこのコードのように: dotnet@githubの ZipArchive.cs )。また、ZipFile API の非同期 APIの欠如に関する未解決の問題も発見しました。
現時点では部分的な非同期サポートがあると思いますが、完全には程遠いです。