Reputation: 19295
So far here's my code:
async Task<bool> HttpDownloadAndUnzip(string requestUri, string directoryToUnzip)
{
using var response = await new HttpClient().GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead);
if (!response.IsSuccessStatusCode) return false;
using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
using var zip = new ZipArchive(streamToReadFrom); // Blocks!
zip.ExtractToDirectory(directoryToUnzip);
return true;
}
What I see tracing with the debugger is that the ZipArchive
constructor blocks until the entire file is downloaded from the URI
This makes the bulk of the operation synchronous whereas I want both downloading and unzipping to be asynchronous.
What is the solution here ? how to make unzipping async ?
PS would be nice to have ExtractToDirectory
async as well
Upvotes: 2
Views: 1659
Reputation: 456577
The ZipArchive
support in .NET only has some very basic asynchronous support.
You could download the stream into memory asynchronously (by removing HttpCompletionOption.ResponseHeadersRead
), and then do the unzipping:
async Task<bool> HttpDownloadAndUnzip(string requestUri, string directoryToUnzip)
{
using var response = await new HttpClient().GetAsync(requestUri);
if (!response.IsSuccessStatusCode) return false;
using var streamToReadFrom = await response.Content.ReadAsStreamAsync();
using var zip = new ZipArchive(streamToReadFrom);
zip.ExtractToDirectory(directoryToUnzip);
return true;
}
I'm not aware of any asynchronous implementations of ExtractToDirectory
in the BCL or any .NET library.
Upvotes: 3
Reputation: 30208
The most simple solution is to wrap your blocking code in
await Task.Run(() =>
{
// blocking code goes here
});
It will still wait for the entire file to download before being viewable, but it will be async
.
To be able to view the contents of a partially downloaded file would require you to write your own unzipper.
Upvotes: 1