Async work #711

Closed
opened 2026-01-29 22:16:17 +00:00 by claunia · 3 comments
Owner

Originally created by @adamhathcock on GitHub (Oct 28, 2025).

Originally assigned to: @adamhathcock on GitHub.

Using AI, I'm converting things to have asynchronous overloads as well as tests for them.

Here's what I think I need to finish:

Stream Classes Needing Async Overloads

Summary

  • 36 classes need ReadAsync overload
  • 17 classes need WriteAsync overload
  • 37 total classes need async overloads (16 need both)

Validation Notes

This list excludes Stream classes where the Write method throws NotSupportedException or NotImplementedException, as these are read-only streams that don't need WriteAsync overloads.

Classes Needing ReadAsync

  • RarCryptoWrapper - src/SharpCompress/Common/Rar/RarCryptoWrapper.cs
  • FolderUnpackStream - src/SharpCompress/Common/SevenZip/ArchiveReader.cs
  • PkwareTraditionalCryptoStream - src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs
  • WinzipAesCryptoStream - src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs
  • ADCStream - src/SharpCompress/Compressors/ADC/ADCStream.cs
  • ArcLzwStream - src/SharpCompress/Compressors/ArcLzw/ArcLzwStream.cs
  • BZip2Stream - src/SharpCompress/Compressors/BZip2/BZip2Stream.cs
  • CBZip2InputStream - src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs
  • CBZip2OutputStream - src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs
  • ExplodeStream - src/SharpCompress/Compressors/Explode/ExplodeStream.cs
  • BCJ2Filter - src/SharpCompress/Compressors/Filters/BCJ2Filter.cs
  • Filter - src/SharpCompress/Compressors/Filters/Filter.cs
  • AesDecoderStream - src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs
  • Bcj2DecoderStream - src/SharpCompress/Compressors/LZMA/Bcj2DecoderStream.cs
  • LZipStream - src/SharpCompress/Compressors/LZMA/LZipStream.cs
  • Decoder - src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs
  • LzmaStream - src/SharpCompress/Compressors/LZMA/LzmaStream.cs
  • CrcBuilderStream - src/SharpCompress/Compressors/LZMA/Utilites/CrcBuilderStream.cs
  • CrcCheckStream - src/SharpCompress/Compressors/LZMA/Utilites/CrcCheckStream.cs
  • LzwStream - src/SharpCompress/Compressors/Lzw/LzwStream.cs
  • PpmdStream - src/SharpCompress/Compressors/PPMd/PpmdStream.cs
  • RunLength90Stream - src/SharpCompress/Compressors/RLE90/RunLength90Stream.cs
  • MultiVolumeReadOnlyStream - src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs
  • RarBLAKE2spStream - src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs
  • RarCrcStream - src/SharpCompress/Compressors/Rar/RarCrcStream.cs
  • RarStream - src/SharpCompress/Compressors/Rar/RarStream.cs
  • ReduceStream - src/SharpCompress/Compressors/Reduce/ReduceStream.cs
  • ShrinkStream - src/SharpCompress/Compressors/Shrink/ShrinkStream.cs
  • SqueezeStream - src/SharpCompress/Compressors/Squeezed/SqueezedStream.cs
  • XZBlock - src/SharpCompress/Compressors/Xz/XZBlock.cs
  • XZStream - src/SharpCompress/Compressors/Xz/XZStream.cs
  • Crc32Stream - src/SharpCompress/Crypto/Crc32Stream.cs
  • BufferedSubStream - src/SharpCompress/IO/BufferedSubStream.cs
  • DataDescriptorStream - src/SharpCompress/IO/DataDescriptorStream.cs
  • ListeningStream - src/SharpCompress/IO/ListeningStream.cs
  • ZipWriter - src/SharpCompress/Writers/Zip/ZipWriter.cs

Classes Needing WriteAsync

  • FolderUnpackStream - src/SharpCompress/Common/SevenZip/ArchiveReader.cs
  • PkwareTraditionalCryptoStream - src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs
  • BZip2Stream - src/SharpCompress/Compressors/BZip2/BZip2Stream.cs
  • CBZip2InputStream - src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs
  • CBZip2OutputStream - src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs
  • Deflate64Stream - src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs
  • Filter - src/SharpCompress/Compressors/Filters/Filter.cs
  • LZipStream - src/SharpCompress/Compressors/LZMA/LZipStream.cs
  • Decoder - src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs
  • LzmaStream - src/SharpCompress/Compressors/LZMA/LzmaStream.cs
  • CrcBuilderStream - src/SharpCompress/Compressors/LZMA/Utilites/CrcBuilderStream.cs
  • CrcCheckStream - src/SharpCompress/Compressors/LZMA/Utilites/CrcCheckStream.cs
  • PpmdStream - src/SharpCompress/Compressors/PPMd/PpmdStream.cs
  • RarStream - src/SharpCompress/Compressors/Rar/RarStream.cs
  • Crc32Stream - src/SharpCompress/Crypto/Crc32Stream.cs
  • ListeningStream - src/SharpCompress/IO/ListeningStream.cs
  • ZipWriter - src/SharpCompress/Writers/Zip/ZipWriter.cs

PRs:
https://github.com/adamhathcock/sharpcompress/pull/978
https://github.com/adamhathcock/sharpcompress/pull/980
https://github.com/adamhathcock/sharpcompress/pull/991

Next is RAR/LZMA/BZip2

Originally created by @adamhathcock on GitHub (Oct 28, 2025). Originally assigned to: @adamhathcock on GitHub. Using AI, I'm converting things to have asynchronous overloads as well as tests for them. Here's what I think I need to finish: # Stream Classes Needing Async Overloads ## Summary - **36** classes need `ReadAsync` overload - **17** classes need `WriteAsync` overload - **37** total classes need async overloads (16 need both) ## Validation Notes This list excludes Stream classes where the `Write` method throws `NotSupportedException` or `NotImplementedException`, as these are read-only streams that don't need `WriteAsync` overloads. ## Classes Needing ReadAsync - `RarCryptoWrapper` - `src/SharpCompress/Common/Rar/RarCryptoWrapper.cs` - `FolderUnpackStream` - `src/SharpCompress/Common/SevenZip/ArchiveReader.cs` - `PkwareTraditionalCryptoStream` - `src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs` - `WinzipAesCryptoStream` - `src/SharpCompress/Common/Zip/WinzipAesCryptoStream.cs` - ~~`ADCStream` - `src/SharpCompress/Compressors/ADC/ADCStream.cs`~~ - `ArcLzwStream` - `src/SharpCompress/Compressors/ArcLzw/ArcLzwStream.cs` - ~~`BZip2Stream` - `src/SharpCompress/Compressors/BZip2/BZip2Stream.cs`~~ - ~~`CBZip2InputStream` - `src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs`~~ - ~~`CBZip2OutputStream` - `src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs`~~ - `ExplodeStream` - `src/SharpCompress/Compressors/Explode/ExplodeStream.cs` - `BCJ2Filter` - `src/SharpCompress/Compressors/Filters/BCJ2Filter.cs` - `Filter` - `src/SharpCompress/Compressors/Filters/Filter.cs` - `AesDecoderStream` - `src/SharpCompress/Compressors/LZMA/AesDecoderStream.cs` - `Bcj2DecoderStream` - `src/SharpCompress/Compressors/LZMA/Bcj2DecoderStream.cs` - ~~`LZipStream` - `src/SharpCompress/Compressors/LZMA/LZipStream.cs`~~ - ~~`Decoder` - `src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs`~~ - ~~`LzmaStream` - `src/SharpCompress/Compressors/LZMA/LzmaStream.cs`~~ - ~~`CrcBuilderStream` - `src/SharpCompress/Compressors/LZMA/Utilites/CrcBuilderStream.cs`~~ - ~~`CrcCheckStream` - `src/SharpCompress/Compressors/LZMA/Utilites/CrcCheckStream.cs`~~ - `LzwStream` - `src/SharpCompress/Compressors/Lzw/LzwStream.cs` - `PpmdStream` - `src/SharpCompress/Compressors/PPMd/PpmdStream.cs` - `RunLength90Stream` - `src/SharpCompress/Compressors/RLE90/RunLength90Stream.cs` - ~~`MultiVolumeReadOnlyStream` - `src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyStream.cs`~~ - ~~`RarBLAKE2spStream` - `src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.cs`~~ - ~~`RarCrcStream` - `src/SharpCompress/Compressors/Rar/RarCrcStream.cs`~~ - ~~`RarStream` - `src/SharpCompress/Compressors/Rar/RarStream.cs`~~ - `ReduceStream` - `src/SharpCompress/Compressors/Reduce/ReduceStream.cs` - `ShrinkStream` - `src/SharpCompress/Compressors/Shrink/ShrinkStream.cs` - `SqueezeStream` - `src/SharpCompress/Compressors/Squeezed/SqueezedStream.cs` - ~~`XZBlock` - `src/SharpCompress/Compressors/Xz/XZBlock.cs`~~ - ~~`XZStream` - `src/SharpCompress/Compressors/Xz/XZStream.cs`~~ - `Crc32Stream` - `src/SharpCompress/Crypto/Crc32Stream.cs` - `BufferedSubStream` - `src/SharpCompress/IO/BufferedSubStream.cs` - `DataDescriptorStream` - `src/SharpCompress/IO/DataDescriptorStream.cs` - `ListeningStream` - `src/SharpCompress/IO/ListeningStream.cs` - `ZipWriter` - `src/SharpCompress/Writers/Zip/ZipWriter.cs` ## Classes Needing WriteAsync - `FolderUnpackStream` - `src/SharpCompress/Common/SevenZip/ArchiveReader.cs` - `PkwareTraditionalCryptoStream` - `src/SharpCompress/Common/Zip/PkwareTraditionalCryptoStream.cs` - ~~`BZip2Stream` - `src/SharpCompress/Compressors/BZip2/BZip2Stream.cs`~~ - ~~`CBZip2InputStream` - `src/SharpCompress/Compressors/BZip2/CBZip2InputStream.cs`~~ - ~~`CBZip2OutputStream` - `src/SharpCompress/Compressors/BZip2/CBZip2OutputStream.cs`~~ - `Deflate64Stream` - `src/SharpCompress/Compressors/Deflate64/Deflate64Stream.cs` - `Filter` - `src/SharpCompress/Compressors/Filters/Filter.cs` - ~~`LZipStream` - `src/SharpCompress/Compressors/LZMA/LZipStream.cs`~~ - ~~`Decoder` - `src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs`~~ - ~~`LzmaStream` - `src/SharpCompress/Compressors/LZMA/LzmaStream.cs`~~ - ~~`CrcBuilderStream` - `src/SharpCompress/Compressors/LZMA/Utilites/CrcBuilderStream.cs`~~ - ~~`CrcCheckStream` - `src/SharpCompress/Compressors/LZMA/Utilites/CrcCheckStream.cs`~~ - `PpmdStream` - `src/SharpCompress/Compressors/PPMd/PpmdStream.cs` - ~~`RarStream` - `src/SharpCompress/Compressors/Rar/RarStream.cs`~~ - `Crc32Stream` - `src/SharpCompress/Crypto/Crc32Stream.cs` - `ListeningStream` - `src/SharpCompress/IO/ListeningStream.cs` - `ZipWriter` - `src/SharpCompress/Writers/Zip/ZipWriter.cs` PRs: https://github.com/adamhathcock/sharpcompress/pull/978 https://github.com/adamhathcock/sharpcompress/pull/980 https://github.com/adamhathcock/sharpcompress/pull/991 Next is RAR/LZMA/BZip2
claunia added the enhancement label 2026-01-29 22:16:17 +00:00
Author
Owner

@rube200 commented on GitHub (Dec 18, 2025):

Hi, i am not sure if this the right place or do you prefer a new issue for this.
Currently i have been having a problem porting from "normal" extraction to async.

This the original code:

    private static async Task ExtractArchiveAsync(SevenZipArchive sevenZipArchive, string destinationFolder,
        CancellationToken cancellationToken)
    {
        var entries = sevenZipArchive.ExtractAllEntries();
        while (entries.MoveToNextEntry())
        {
            cancellationToken.ThrowIfCancellationRequested();

            var entry = entries.Entry;
            if (entry.IsDirectory || entry.Key is null)
                continue;

            var expectedLocation = Path.Combine(destinationFolder, entry.Key);
            if (entry.Size == FileRepository.SizeOf(expectedLocation))
                continue;

            await using var fileStream = FileRepository.Create(expectedLocation);
            entries.WriteEntryTo(fileStream);
        }
    }

ìf i change any of those(or both) to async equivalent it always fails.
while (entries.MoveToNextEntry()) => while (await entries.MoveToNextEntryAsync(cancellationToken))
or
entries.WriteEntryTo(fileStream); => await entries.WriteEntryToAsync(fileStream, cancellationToken);

I always receive the error:

SharpCompress.Compressors.LZMA.DataErrorException: Data Error
         at SharpCompress.Compressors.LZMA.Decoder.CodeAsync(Int32 dictionarySize, OutWindow outWindow, Decoder rangeDecoder, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs:line 605
         at SharpCompress.Compressors.LZMA.LzmaStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaStream.cs:line 562
         at SharpCompress.IO.ReadOnlySubStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/IO/ReadOnlySubStream.cs:line 109
         at SharpCompress.Common.EntryStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 164
         at SharpCompress.Utility.SkipAsync(Stream source, CancellationToken cancellationToken) in /_/src/SharpCompress/Utility.cs:line 104
         at SharpCompress.Common.EntryStream.SkipEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 61
         at SharpCompress.Common.EntryStream.DisposeAsync() in /_/src/SharpCompress/Common/EntryStream.cs:line 106
         at SharpCompress.Readers.AbstractReader`2.SkipAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 212
         at SharpCompress.Readers.AbstractReader`2.SkipEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 163
         at SharpCompress.Readers.AbstractReader`2.MoveToNextEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 115

or

SharpCompress.Compressors.LZMA.DataErrorException: Data Error
         at SharpCompress.Compressors.LZMA.Decoder.CodeAsync(Int32 dictionarySize, OutWindow outWindow, Decoder rangeDecoder, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs:line 605
         at SharpCompress.Compressors.LZMA.LzmaStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaStream.cs:line 562
         at SharpCompress.IO.ReadOnlySubStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/IO/ReadOnlySubStream.cs:line 109
         at SharpCompress.Common.EntryStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 164
         at SharpCompress.Utility.SkipAsync(Stream source, CancellationToken cancellationToken) in /_/src/SharpCompress/Utility.cs:line 104
         at SharpCompress.Common.EntryStream.SkipEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 61
         at SharpCompress.Common.EntryStream.DisposeAsync() in /_/src/SharpCompress/Common/EntryStream.cs:line 106
         at SharpCompress.Readers.AbstractReader`2.WriteAsync(Stream writeStream, CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 281
         at SharpCompress.Readers.AbstractReader`2.WriteEntryToAsync(Stream writableStream, CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 261

Code condition:

if (_rep0 >= outWindow.Total || _rep0 >= dictionarySizeCheck)
{
    if (_rep0 == 0xFFFFFFFF)
    {
        return true;
    }
    throw new DataErrorException();
}
@rube200 commented on GitHub (Dec 18, 2025): Hi, i am not sure if this the right place or do you prefer a new issue for this. Currently i have been having a problem porting from "normal" extraction to async. This the original code: ```c# private static async Task ExtractArchiveAsync(SevenZipArchive sevenZipArchive, string destinationFolder, CancellationToken cancellationToken) { var entries = sevenZipArchive.ExtractAllEntries(); while (entries.MoveToNextEntry()) { cancellationToken.ThrowIfCancellationRequested(); var entry = entries.Entry; if (entry.IsDirectory || entry.Key is null) continue; var expectedLocation = Path.Combine(destinationFolder, entry.Key); if (entry.Size == FileRepository.SizeOf(expectedLocation)) continue; await using var fileStream = FileRepository.Create(expectedLocation); entries.WriteEntryTo(fileStream); } } ``` ìf i change any of those(or both) to async equivalent it always fails. `while (entries.MoveToNextEntry())` => `while (await entries.MoveToNextEntryAsync(cancellationToken))` or `entries.WriteEntryTo(fileStream);` => `await entries.WriteEntryToAsync(fileStream, cancellationToken);` I always receive the error: ``` SharpCompress.Compressors.LZMA.DataErrorException: Data Error at SharpCompress.Compressors.LZMA.Decoder.CodeAsync(Int32 dictionarySize, OutWindow outWindow, Decoder rangeDecoder, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs:line 605 at SharpCompress.Compressors.LZMA.LzmaStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaStream.cs:line 562 at SharpCompress.IO.ReadOnlySubStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/IO/ReadOnlySubStream.cs:line 109 at SharpCompress.Common.EntryStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 164 at SharpCompress.Utility.SkipAsync(Stream source, CancellationToken cancellationToken) in /_/src/SharpCompress/Utility.cs:line 104 at SharpCompress.Common.EntryStream.SkipEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 61 at SharpCompress.Common.EntryStream.DisposeAsync() in /_/src/SharpCompress/Common/EntryStream.cs:line 106 at SharpCompress.Readers.AbstractReader`2.SkipAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 212 at SharpCompress.Readers.AbstractReader`2.SkipEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 163 at SharpCompress.Readers.AbstractReader`2.MoveToNextEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 115 ``` or ``` SharpCompress.Compressors.LZMA.DataErrorException: Data Error at SharpCompress.Compressors.LZMA.Decoder.CodeAsync(Int32 dictionarySize, OutWindow outWindow, Decoder rangeDecoder, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaDecoder.cs:line 605 at SharpCompress.Compressors.LZMA.LzmaStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Compressors/LZMA/LzmaStream.cs:line 562 at SharpCompress.IO.ReadOnlySubStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/IO/ReadOnlySubStream.cs:line 109 at SharpCompress.Common.EntryStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 164 at SharpCompress.Utility.SkipAsync(Stream source, CancellationToken cancellationToken) in /_/src/SharpCompress/Utility.cs:line 104 at SharpCompress.Common.EntryStream.SkipEntryAsync(CancellationToken cancellationToken) in /_/src/SharpCompress/Common/EntryStream.cs:line 61 at SharpCompress.Common.EntryStream.DisposeAsync() in /_/src/SharpCompress/Common/EntryStream.cs:line 106 at SharpCompress.Readers.AbstractReader`2.WriteAsync(Stream writeStream, CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 281 at SharpCompress.Readers.AbstractReader`2.WriteEntryToAsync(Stream writableStream, CancellationToken cancellationToken) in /_/src/SharpCompress/Readers/AbstractReader.cs:line 261 ``` Code condition: ```C# if (_rep0 >= outWindow.Total || _rep0 >= dictionarySizeCheck) { if (_rep0 == 0xFFFFFFFF) { return true; } throw new DataErrorException(); } ```
Author
Owner

@adamhathcock commented on GitHub (Dec 19, 2025):

I was just seeing this type of thing yesterday with 7zip files. I'll dig deeper

@adamhathcock commented on GitHub (Dec 19, 2025): I was just seeing this type of thing yesterday with 7zip files. I'll dig deeper
Author
Owner

@adamhathcock commented on GitHub (Dec 19, 2025):

This should have been another issue but I think it's fixed with https://github.com/adamhathcock/sharpcompress/pull/1076

The LZMA implementation needs to be looked at harder

@adamhathcock commented on GitHub (Dec 19, 2025): This should have been another issue but I think it's fixed with https://github.com/adamhathcock/sharpcompress/pull/1076 The LZMA implementation needs to be looked at harder
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/sharpcompress#711