6

.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 つの質問があります。

  1. クラス (または他のサードパーティの .NET ライブラリ)で非同期 I/O を取得することは可能System.IO.Compressionですか?
  2. それをするのは理にかなっていますか?とにかく、圧縮/抽出アルゴリズムは非常に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の欠如に関する未解決の問題も発見しました。

現時点では部分的な非同期サポートがあると思いますが、完全には程遠いです。

4

1 に答える 1

9
  1. クラス (または他のサードパーティの .NET ライブラリ)で非同期 I/O を取得することは可能System.IO.Compressionですか?

「非同期 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 に切り替えても、パフォーマンスの向上は比較的小さい可能性があります (もちろん、絶対値ではなくパーセンテージで)。

そうする少なくとも3つの理由:

  1. CPU は非常に高速です。多くの場合、I/O は依然としてボトルネックであるため、I/O を非同期に待機することが役立ちます。
  2. マルチコア CPU は標準です。そのため、1 つのコアで解凍を行い、別のコアで他の作業を行うと便利です。
  3. 非同期操作は完全にパフォーマンスに関するものではなく、場合によってはまったくパフォーマンスに関するものではありません。アーカイブを非同期で処理すると、ユーザー インターフェイスの応答性を維持できるので便利です。
于 2016-09-10T00:30:53.140 に答える