Skip to content

Comments

add configure await#1195

Merged
adamhathcock merged 9 commits intomasterfrom
adam/add-configure-await
Feb 10, 2026
Merged

add configure await#1195
adamhathcock merged 9 commits intomasterfrom
adam/add-configure-await

Conversation

@adamhathcock
Copy link
Owner

This pull request ensures consistent and correct asynchronous programming practices across the codebase by adding .ConfigureAwait(false) to all await expressions in asynchronous methods. This change improves reliability and prevents potential deadlocks, especially in library code that may be used in various synchronization contexts. The updates span multiple archive types and extension methods.

The most important changes include:

Async Await Consistency and Reliability:

Archive Type-Specific Updates:

  • Applied .ConfigureAwait(false) to all async operations in RAR and GZip archive classes and their extension methods, ensuring consistent asynchronous behavior across archive types. [1] [2] [3] [4]

Extension Methods and Utility Updates:

  • Updated extension methods such as WriteToAsync, WriteToDirectoryAsync, and AddEntryAsync to use .ConfigureAwait(false) after all asynchronous calls. [1] [2] [3] [4] [5]

These changes collectively make the async code safer and more predictable for consumers, especially in library and cross-platform scenarios.

Copilot AI review requested due to automatic review settings February 10, 2026 13:56
@kiloconnect
Copy link
Contributor

kiloconnect bot commented Feb 10, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
src/SharpCompress/Polyfills/AsyncEnumerableExtensions.cs 13 Empty<T>() uses await Task.Yield() unnecessarily - can be simplified
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
src/SharpCompress/Compressors/ADC/ADCBase.Async.cs 23 Disposable MemoryStream is created but not disposed - consider using using
src/SharpCompress/Common/Arj/Headers/ArjHeader.Async.cs 44 Assignment to read variable is unused (immediately overwritten on line 52)
Files Reviewed (X files)
  • src/SharpCompress/Polyfills/AsyncEnumerableExtensions.cs - 1 suggestion
  • src/SharpCompress/Compressors/ADC/ADCBase.Async.cs - 1 observation (outside diff)
  • src/SharpCompress/Common/Arj/Headers/ArjHeader.Async.cs - 1 observation (outside diff)
  • src/SharpCompress/Compressors/BZip2/CBZip2InputStream.Async.cs - no new issues
  • Plus 50+ other files with .ConfigureAwait(false) additions - all look correct

Fix these issues in Kilo Cloud

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR standardizes async behavior across SharpCompress by adding .ConfigureAwait(false) to awaited operations throughout archives/readers/writers and related helpers, aiming to avoid synchronization-context capture in library code.

Changes:

  • Added .ConfigureAwait(false) to awaited operations across archive/reader/writer async paths.
  • Updated async factory/detection logic to consistently avoid context capture.
  • Adjusted several async iterator/helper implementations while applying the pattern.

Reviewed changes

Copilot reviewed 82 out of 82 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/SharpCompress/Writers/Tar/TarWriter.Async.cs Add .ConfigureAwait(false) to delegated async write call.
src/SharpCompress/Writers/GZip/GZipWriter.Async.cs Add .ConfigureAwait(false) to CopyToAsync awaits.
src/SharpCompress/Readers/ReaderFactory.Async.cs Add .ConfigureAwait(false) to async factory probing/opening.
src/SharpCompress/Readers/Rar/RarReader.Async.cs Add .ConfigureAwait(false) to multivolume stream creation await.
src/SharpCompress/Readers/Rar/MultiVolumeRarReader.Async.cs Add .ConfigureAwait(false) to stream-load awaits.
src/SharpCompress/Readers/IAsyncReaderExtensions.cs Add .ConfigureAwait(false) to MoveToNextEntryAsync in loop condition.
src/SharpCompress/Readers/Arj/ArjReader.cs Add .ConfigureAwait(false) to header read awaits.
src/SharpCompress/Readers/Arc/ArcReader.Async.cs Add .ConfigureAwait(false) to header read await in loop condition.
src/SharpCompress/Readers/Ace/AceReader.cs Add .ConfigureAwait(false) to header read awaits.
src/SharpCompress/Readers/AbstractReader.Async.cs Add .ConfigureAwait(false) to disposal/enumerator awaits; removed placeholder await in async iterator.
src/SharpCompress/Polyfills/AsyncEnumerableExtensions.cs Add .ConfigureAwait(false) to enumerator awaits; removed placeholder awaits in async iterators.
src/SharpCompress/LazyAsyncReadOnlyCollection.cs Add .ConfigureAwait(false) to source enumerator movement awaits.
src/SharpCompress/IO/SharpCompressStream.Async.cs Add .ConfigureAwait(false) to read/write/dispose awaits in copy loop and disposal.
src/SharpCompress/Factories/ZipFactory.cs Add .ConfigureAwait(false) to zip detection awaits.
src/SharpCompress/Factories/TarWrapper.cs Add .ConfigureAwait(false) to wrapper stream creation awaits.
src/SharpCompress/Factories/TarFactory.cs Add .ConfigureAwait(false) to wrapper match/decompress/tar-detect awaits.
src/SharpCompress/Factories/ArcFactory.cs Add .ConfigureAwait(false) to ReadExactAsync await.
src/SharpCompress/Compressors/ZStandard/ZStandardStream.Async.cs Add .ConfigureAwait(false) to header read await.
src/SharpCompress/Compressors/Rar/RarStream.Async.cs Add .ConfigureAwait(false) to unpack initialization await.
src/SharpCompress/Compressors/Rar/RarCrcStream.Async.cs Add .ConfigureAwait(false) to stream initialization await.
src/SharpCompress/Compressors/Rar/RarBLAKE2spStream.Async.cs Add .ConfigureAwait(false) to stream initialization await.
src/SharpCompress/Compressors/Rar/MultiVolumeReadOnlyAsyncStream.Async.cs Add .ConfigureAwait(false) to enumerator/dispose/move-next awaits.
src/SharpCompress/Compressors/Lzw/LzwStream.Async.cs Add .ConfigureAwait(false) to header read await.
src/SharpCompress/Compressors/LZMA/Utilites/CrcBuilderStream.Async.cs Add .ConfigureAwait(false) to target write await.
src/SharpCompress/Compressors/LZMA/LzmaStream.Async.cs Add .ConfigureAwait(false) to init/train decoder awaits.
src/SharpCompress/Compressors/LZMA/LzmaDecoder.Async.cs Add .ConfigureAwait(false) to decoder/bit-tree/literal decode awaits.
src/SharpCompress/Compressors/LZMA/LZipStream.Async.cs Add .ConfigureAwait(false) to validation/write awaits.
src/SharpCompress/Compressors/LZMA/LZ/LzOutWindow.Async.cs Add .ConfigureAwait(false) to init/release/train awaits.
src/SharpCompress/Compressors/LZMA/DecoderRegistry.Async.cs Add .ConfigureAwait(false) to decoder stream creation awaits.
src/SharpCompress/Compressors/BZip2/CBZip2InputStream.Async.cs Add .ConfigureAwait(false) to read/initialization awaits; removed placeholder await in an async method.
src/SharpCompress/Compressors/BZip2/BZip2Stream.Async.cs Add .ConfigureAwait(false) to stream creation and header read awaits.
src/SharpCompress/Compressors/ADC/ADCStream.Async.cs Add .ConfigureAwait(false) to decompression awaits.
src/SharpCompress/Compressors/ADC/ADCBase.Async.cs Add .ConfigureAwait(false) to overload and stream read awaits.
src/SharpCompress/Common/Zip/ZipHeaderFactory.Async.cs Add .ConfigureAwait(false) to header parsing awaits.
src/SharpCompress/Common/Zip/ZipFilePart.Async.cs Add .ConfigureAwait(false) to decompressor creation awaits and recursive call await.
src/SharpCompress/Common/Zip/SeekableZipHeaderFactory.Async.cs Add .ConfigureAwait(false) to seek/read/header parse awaits.
src/SharpCompress/Common/Zip/SeekableZipFilePart.Async.cs Add .ConfigureAwait(false) to local-header load and base call awaits.
src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndLocatorHeader.Async.cs Add .ConfigureAwait(false) to primitive read awaits.
src/SharpCompress/Common/Zip/Headers/Zip64DirectoryEndHeader.Async.cs Add .ConfigureAwait(false) to primitive/byte reads.
src/SharpCompress/Common/Zip/Headers/LocalEntryHeader.Async.cs Add .ConfigureAwait(false) to primitive/byte reads.
src/SharpCompress/Common/Zip/Headers/DirectoryEntryHeader.Async.cs Add .ConfigureAwait(false) to primitive/byte reads.
src/SharpCompress/Common/Zip/Headers/DirectoryEndHeader.Async.cs Add .ConfigureAwait(false) to primitive/byte reads.
src/SharpCompress/Common/Tar/TarHeaderFactory.Async.cs Add .ConfigureAwait(false) to tar header read await.
src/SharpCompress/Common/Tar/Headers/TarHeader.Async.cs Add .ConfigureAwait(false) to tar read/write helper awaits.
src/SharpCompress/Common/SevenZip/SevenZipFilePart.cs Add .ConfigureAwait(false) to folder stream/skip awaits.
src/SharpCompress/Common/SevenZip/ArchiveReader.Async.cs Add .ConfigureAwait(false) to signature/header reads.
src/SharpCompress/Common/Rar/RarVolume.cs Add .ConfigureAwait(false) to read/ensure header-load awaits.
src/SharpCompress/Common/Rar/Rar5CryptoInfo.cs Add .ConfigureAwait(false) to async binary reader operations.
src/SharpCompress/Common/Rar/Headers/RarHeaderFactory.Async.cs Add .ConfigureAwait(false) to crypt reader setup awaits.
src/SharpCompress/Common/Rar/Headers/FileHeader.Async.cs Add .ConfigureAwait(false) to salt read await.
src/SharpCompress/Common/Rar/Headers/ArchiveCryptHeader.Async.cs Add .ConfigureAwait(false) to crypto info creation await.
src/SharpCompress/Common/Rar/AsyncRarCryptoBinaryReader.cs Add .ConfigureAwait(false) to salt read await.
src/SharpCompress/Common/GZip/GZipFilePart.Async.cs Add .ConfigureAwait(false) to header/trailer/string read awaits.
src/SharpCompress/Common/GZip/GZipEntry.Async.cs Add .ConfigureAwait(false) to part creation await.
src/SharpCompress/Common/Arj/Headers/ArjMainHeader.Async.cs Add .ConfigureAwait(false) to header/extended header awaits.
src/SharpCompress/Common/Arj/Headers/ArjLocalHeader.Async.cs Add .ConfigureAwait(false) to header/extended header awaits.
src/SharpCompress/Common/Arj/Headers/ArjHeader.Async.cs Add .ConfigureAwait(false) to stream read awaits in header parsing and detection.
src/SharpCompress/Common/Arc/ArcFilePart.Async.cs Add .ConfigureAwait(false) to squeezed stream creation await.
src/SharpCompress/Common/Arc/ArcEntryHeader.cs Add .ConfigureAwait(false) to entry header read await.
src/SharpCompress/Common/Ace/Headers/AceMainHeader.Async.cs Add .ConfigureAwait(false) to main header read await.
src/SharpCompress/Common/Ace/Headers/AceHeader.Async.cs Add .ConfigureAwait(false) to header reads.
src/SharpCompress/Common/Ace/Headers/AceFileHeader.Async.cs Add .ConfigureAwait(false) to file header read await.
src/SharpCompress/Archives/Zip/ZipArchiveEntry.Async.cs Add .ConfigureAwait(false) to seekable compressed-stream await.
src/SharpCompress/Archives/Zip/ZipArchive.Factory.cs Add .ConfigureAwait(false) to async header enumeration and async seekable header reads.
src/SharpCompress/Archives/Zip/ZipArchive.Async.cs Add .ConfigureAwait(false) to volume list materialization await.
src/SharpCompress/Archives/Tar/TarArchiveEntry.cs Add .ConfigureAwait(false) to compressed stream await.
src/SharpCompress/Archives/Tar/TarArchive.Factory.cs Add .ConfigureAwait(false) to tar header read await.
src/SharpCompress/Archives/Tar/TarArchive.Async.cs Add .ConfigureAwait(false) to volume selection and entry copy await.
src/SharpCompress/Archives/SevenZip/SevenZipArchiveEntry.cs Add .ConfigureAwait(false) to compressed stream await.
src/SharpCompress/Archives/SevenZip/SevenZipArchive.Factory.cs Add .ConfigureAwait(false) to signature match await.
src/SharpCompress/Archives/SevenZip/SevenZipArchive.Async.cs Add .ConfigureAwait(false) to reader open/database load and volume selection awaits.
src/SharpCompress/Archives/Rar/RarArchiveEntry.Async.cs Add .ConfigureAwait(false) to multivolume stream creation and init awaits.
src/SharpCompress/Archives/Rar/RarArchive.Extensions.cs Add .ConfigureAwait(false) to first-volume retrieval awaits.
src/SharpCompress/Archives/Rar/RarArchive.Async.cs Add .ConfigureAwait(false) to disposal, multipart checks, volume enumeration, and solid checks.
src/SharpCompress/Archives/IWritableAsyncArchiveExtensions.cs Add .ConfigureAwait(false) to AddEntryAsync await in file enumeration loop.
src/SharpCompress/Archives/IAsyncArchiveExtensions.cs Add .ConfigureAwait(false) to IsSolidAsync, ExtractAllEntriesAsync, internal write, and size aggregation awaits.
src/SharpCompress/Archives/IArchiveEntryExtensions.cs Add .ConfigureAwait(false) to OpenEntryStreamAsync awaits for both legacy and async-disposable paths.
src/SharpCompress/Archives/GZip/GZipArchive.Async.cs Add .ConfigureAwait(false) to entry stream opens, volume selection, and file part creation awaits.
src/SharpCompress/Archives/ArchiveFactory.Async.cs Add .ConfigureAwait(false) to factory discovery and delegated open awaits.
src/SharpCompress/Archives/AbstractWritableArchive.cs Add .ConfigureAwait(false) to explicit interface async delegates.
src/SharpCompress/Archives/AbstractWritableArchive.Async.cs Add .ConfigureAwait(false) to rebuild-modified-collection awaits.
src/SharpCompress/Archives/AbstractArchive.Async.cs Add .ConfigureAwait(false) to volume materialization, lazy-load, solid checks, aggregate/all awaits.
Comments suppressed due to low confidence (2)

src/SharpCompress/Polyfills/AsyncEnumerableExtensions.cs:27

  • ToAsyncEnumerable is still async IAsyncEnumerable<T> but now has no await, which can trigger CS1998 and fail the build with warnings-as-errors. Restore the previous no-op await (with ConfigureAwait(false)) or adjust the implementation so the async iterator contains at least one awaited operation.
    src/SharpCompress/Readers/AbstractReader.Async.cs:208
  • GetEntriesAsync is an async iterator but now contains no await (the previous Task.CompletedTask placeholder was removed). With TreatWarningsAsErrors=true, this can trigger CS1998 and fail the build. Either restore a no-op awaited task (with ConfigureAwait(false)) or refactor to avoid an async method body without awaits.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


byte[] crc = new byte[4];
read = await stream.ReadAsync(crc, 0, 4, cancellationToken);
read = await stream.ReadAsync(crc, 0, 4, cancellationToken).ConfigureAwait(false);
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to read is useless, since its value is never read.

Suggested change
read = await stream.ReadAsync(crc, 0, 4, cancellationToken).ConfigureAwait(false);
read = await stream.ReadAsync(crc, 0, 4, cancellationToken).ConfigureAwait(false);
if (read < 4)
{
return Array.Empty<byte>();
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant