Cancel archive extraction with CancellationToken
Long extraction operations are not always supposed to run to completion. A user can press a Cancel button, a web request can time out, a background worker can be stopped by the host, or your application can decide that the current job has already exceeded its time budget. In all these cases it is better to stop decompression than to keep spending CPU time, disk I/O, and temporary storage on data that is no longer needed.
Aspose.ZIP for .NET supports this scenario through CancellationToken. You assign the token in a format-specific load options class when opening an archive, and extraction methods observe that token while decompressing data.
When cancellation is useful
- A desktop or web UI lets the user interrupt a long extraction.
- An ASP.NET request is aborted and the response is no longer needed.
- A scheduled or queued job must finish within a timeout window.
- A hosted service is shutting down and should stop ongoing work gracefully.
- You want to extract into a temporary location only while the operation is still relevant.
About cts.CancelAfter()
In the samples below you will see cts.CancelAfter(20);. That line tells CancellationTokenSource to trigger cancellation after 20 milliseconds. The value 20 is used only to make the sample cancel quickly and predictably. It is not a recommended timeout and it is not related to any archive format. If extraction finishes before that timeout expires, the operation completes normally.
In a real application you will often do one of these instead:
- call
cts.Cancel()when the user clicks Cancel; - pass an existing token such as a request-abort or shutdown token;
- choose a timeout that matches your own SLA or job budget.
Cancellation stops extraction as soon as the current operation notices the token. Some output may already exist at that point. If you extract an entry to a stream, that stream can contain partial data. If you call ExtractToDirectory, the destination folder can already contain some extracted files. If you need all-or-nothing behavior, extract to a temporary location and remove it after cancellation.
ZIP
ZIP archives use ArchiveLoadOptions. The same token can be used both for extracting a particular entry and for extracting the whole archive to a directory.
1 // Cancel extraction of a particular ZIP entry.
2 using (CancellationTokenSource cts = new CancellationTokenSource())
3 {
4 cts.CancelAfter(20); // Demo timeout: cancel after 20 ms.
5
6 try
7 {
8 using (Archive archive = new Archive("archive.zip",
9 new ArchiveLoadOptions() { CancellationToken = cts.Token }))
10 using (MemoryStream output = new MemoryStream())
11 {
12 archive.Entries[0].Extract(output);
13 }
14 }
15 catch (OperationCanceledException)
16 {
17 Console.WriteLine("ZIP entry extraction was canceled.");
18 }
19 }
20
21 // Cancel extraction of the whole ZIP archive.
22 using (CancellationTokenSource cts = new CancellationTokenSource())
23 {
24 cts.CancelAfter(20); // Demo timeout: cancel after 20 ms.
25
26 try
27 {
28 using (Archive archive = new Archive("archive.zip",
29 new ArchiveLoadOptions() { CancellationToken = cts.Token }))
30 {
31 archive.ExtractToDirectory("zip-out");
32 }
33 }
34 catch (OperationCanceledException)
35 {
36 Console.WriteLine("ZIP archive extraction was canceled.");
37 }
38 }7z
7z archives use SevenZipLoadOptions.
1 // Cancel extraction of a particular 7z entry.
2 using (CancellationTokenSource cts = new CancellationTokenSource())
3 {
4 cts.CancelAfter(20);
5
6 try
7 {
8 using (SevenZipArchive archive = new SevenZipArchive("archive.7z",
9 new SevenZipLoadOptions() { CancellationToken = cts.Token }))
10 using (MemoryStream output = new MemoryStream())
11 {
12 archive.Entries[0].Extract(output);
13 }
14 }
15 catch (OperationCanceledException)
16 {
17 Console.WriteLine("7z entry extraction was canceled.");
18 }
19 }
20
21 // Cancel extraction of the whole 7z archive.
22 using (CancellationTokenSource cts = new CancellationTokenSource())
23 {
24 cts.CancelAfter(20);
25
26 try
27 {
28 using (SevenZipArchive archive = new SevenZipArchive("archive.7z",
29 new SevenZipLoadOptions() { CancellationToken = cts.Token }))
30 {
31 archive.ExtractToDirectory("7z-out");
32 }
33 }
34 catch (OperationCanceledException)
35 {
36 Console.WriteLine("7z archive extraction was canceled.");
37 }
38 }CAB
CAB archives use CabLoadOptions.
1 // Cancel extraction of a particular CAB entry.
2 using (CancellationTokenSource cts = new CancellationTokenSource())
3 {
4 cts.CancelAfter(20);
5
6 try
7 {
8 using (CabArchive archive = new CabArchive("archive.cab",
9 new CabLoadOptions() { CancellationToken = cts.Token }))
10 using (MemoryStream output = new MemoryStream())
11 {
12 archive.Entries[0].Extract(output);
13 }
14 }
15 catch (OperationCanceledException)
16 {
17 Console.WriteLine("CAB entry extraction was canceled.");
18 }
19 }
20
21 // Cancel extraction of the whole CAB archive.
22 using (CancellationTokenSource cts = new CancellationTokenSource())
23 {
24 cts.CancelAfter(20);
25
26 try
27 {
28 using (CabArchive archive = new CabArchive("archive.cab",
29 new CabLoadOptions() { CancellationToken = cts.Token }))
30 {
31 archive.ExtractToDirectory("cab-out");
32 }
33 }
34 catch (OperationCanceledException)
35 {
36 Console.WriteLine("CAB archive extraction was canceled.");
37 }
38 }RAR
RAR archives use RarArchiveLoadOptions.
1 // Cancel extraction of a particular RAR entry.
2 using (CancellationTokenSource cts = new CancellationTokenSource())
3 {
4 cts.CancelAfter(20);
5
6 try
7 {
8 using (RarArchive archive = new RarArchive("archive.rar",
9 new RarArchiveLoadOptions() { CancellationToken = cts.Token }))
10 using (MemoryStream output = new MemoryStream())
11 {
12 archive.Entries[0].Extract(output);
13 }
14 }
15 catch (OperationCanceledException)
16 {
17 Console.WriteLine("RAR entry extraction was canceled.");
18 }
19 }
20
21 // Cancel extraction of the whole RAR archive.
22 using (CancellationTokenSource cts = new CancellationTokenSource())
23 {
24 cts.CancelAfter(20);
25
26 try
27 {
28 using (RarArchive archive = new RarArchive("archive.rar",
29 new RarArchiveLoadOptions() { CancellationToken = cts.Token }))
30 {
31 archive.ExtractToDirectory("rar-out");
32 }
33 }
34 catch (OperationCanceledException)
35 {
36 Console.WriteLine("RAR archive extraction was canceled.");
37 }
38 }GZIP, BZIP2, LZ4, LZIP, XZ, Z, and Zstandard
These formats carry a single compressed data stream rather than an entry collection. The cancellation pattern is the same: create a token, pass it in load options, then call Extract.
The sample below uses GZIP. Replace GzipArchive and GzipLoadOptions with the matching classes for BZIP2, LZ4, LZIP, XZ, Z, or Zstandard.
1 using (CancellationTokenSource cts = new CancellationTokenSource())
2 {
3 cts.CancelAfter(20);
4
5 try
6 {
7 using (GzipArchive archive = new GzipArchive("data.txt.gz",
8 new GzipLoadOptions() { CancellationToken = cts.Token }))
9 using (MemoryStream output = new MemoryStream())
10 {
11 archive.Extract(output);
12 }
13 }
14 catch (OperationCanceledException)
15 {
16 Console.WriteLine("Single-stream archive extraction was canceled.");
17 }
18 }ARJ, ISO, LHA, LZX, WIM, and XAR
This group also supports cancellation through format-specific load options. The sample below uses ISO for the entry-based pattern: extracting one file or extracting the whole archive to a directory.
1 // Cancel extraction of a single file from an ISO image.
2 using (CancellationTokenSource cts = new CancellationTokenSource())
3 {
4 cts.CancelAfter(20);
5
6 try
7 {
8 using (IsoArchive archive = new IsoArchive("image.iso",
9 new IsoLoadOptions() { CancellationToken = cts.Token }))
10 using (MemoryStream output = new MemoryStream())
11 {
12 var fileEntry = archive.Entries.First(entry => !entry.IsDirectory);
13 fileEntry.Extract(output);
14 }
15 }
16 catch (OperationCanceledException)
17 {
18 Console.WriteLine("ISO entry extraction was canceled.");
19 }
20 }
21
22 // Cancel extraction of the whole ISO image.
23 using (CancellationTokenSource cts = new CancellationTokenSource())
24 {
25 cts.CancelAfter(20);
26
27 try
28 {
29 using (IsoArchive archive = new IsoArchive("image.iso",
30 new IsoLoadOptions() { CancellationToken = cts.Token }))
31 {
32 archive.ExtractToDirectory("iso-out");
33 }
34 }
35 catch (OperationCanceledException)
36 {
37 Console.WriteLine("ISO extraction was canceled.");
38 }
39 }ARJ, LHA, LZX, and XAR use the same load-options-based approach. WIM also supports cancellation through WimLoadOptions; when extracting a whole image you typically call wimArchive.Images[0].ExtractToDirectory(...).