.NET 4.5では、zipアーカイブで動作する新しいクラスが追加されました。あなたが大規模なアーカイブで作業している場合、それはアーカイブからファイルを読み取るために秒あるいは数分かかる場合があり、明らかにSystem.IO.Compressionおよびasync I/OのZipFileおよびZipArchiveクラス
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年の「クールじゃない」と考えられているblocking modeに実行されるように、2つの質問があります。
- はそれが非同期Iを取得することが可能です/ O
System.IO.Compression
クラス(または多分他のサードパーティの.NETライブラリと)? - これを行うことは理にかなっていますか?私は圧縮/抽出アルゴリズムはとにかくCPUを消費しているので、
CPUバインドからI/Oを非同期I/Oにブロックする場合でも、パフォーマンスの利得は比較的小さくなります(もちろん、絶対値ではありません) )。
UPDATE:
ピーター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をブロックしています(ZipArchive.cs on [email protected]など)。私はlack of asynchronous API for ZipFile APIsに関する未解決の問題も発見しました。
私たちは部分非同期サポートをしていると思いますが、完全ではありません。
_ "I/O操作をCPUでブロックすることはありますが、別のスレッドで実行します。" CPUがデータを格納できる速度よりも速くデータを解凍できる限り、それはまだI/Oにバインドされています(しかし、SSDストレージは、より高速な時間を前もって推測することを困難にします)。これは、私が「非同期I/O」の意味に依存していると書いた理由です。すべてのI/Oは本質的に非同期です。これはAPI(たとえば多くの.NET I/Oメソッドが基づいているIOCP)に浮上していることがあります。時にはそうではありません。しかし、I/O操作は、どのように起動するかにかかわらず、CPUを消費しません。 –
はい、そうです、I/O操作はCPUを消費しません。非同期I/Oとは、このI/O操作を要求したスレッドをブロックしないようなAPI関数を意味します。 –
I/O操作がスレッドをブロックするのを避けることができれば、明らかに良いでしょう。しかし、スレッドプールはI/O操作の間にスレッドが一時的にブロックされていると合理的にうまく対処します。主なことは、そうでなければ何か有用なスレッドをブロックしないことです。それが本当に重要なのであれば、 'ExtractToFile()'のようなメソッドは、スレッドを使わない真の非同期I/Oメソッドとして実装するのは簡単です(既に上記のアップデートで示したように)。 –