[英]Download & extract zip file using Async / Await with progress reporting
I want to implement a re-usable class that will facilitate with downloading a given zip file and extract it, whilst reporting progress using the C# 5 await/async feature. 我想实现一个可重用的类,该类将有助于下载给定的zip文件并解压缩它,同时使用C#5等待/异步功能报告进度。
I am new to this and trying to wrap my head around it at the moment. 我对此并不陌生,目前正设法将其包裹住。 This is my Installer class so far:
到目前为止,这是我的Installer类:
class Installer
{
Button saveButton;
ProgressBar progressBar;
Label statusLabel;
Boolean downloadDone;
public Installer(Button _saveButton, ProgressBar _progressBar, Label _statusLabel)
{
saveButton = _saveButton;
progressBar = _progressBar;
statusLabel = _statusLabel;
}
public async void Start(string fileUrl)
{
saveButton.BeginInvoke((Action)(() => {
saveButton.Enabled = false;
}));
Task<bool> downloadArchiveTask = DownloadArchiveAsync(fileUrl);
bool downloadArchiveDone = await downloadArchiveTask;
if (downloadArchiveDone)
statusLabel.BeginInvoke((Action)(() => {
statusLabel.Text = "Download Completed";
}));
}
async Task<bool> DownloadArchiveAsync(string fileUrl)
{
var downloadLink = new Uri(fileUrl);
var saveFilename = Path.GetFileName(downloadLink.AbsolutePath);
DownloadProgressChangedEventHandler DownloadProgressChangedEvent = (s, e) =>
{
progressBar.BeginInvoke((Action)(() => {
progressBar.Value = e.ProgressPercentage;
}));
var downloadProgress = string.Format("{0} MB / {1} MB",
(e.BytesReceived / 1024d / 1024d).ToString("0.00"),
(e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
statusLabel.BeginInvoke((Action)(() => {
statusLabel.Text = "Downloading " + downloadProgress + " ...";
}));
};
AsyncCompletedEventHandler AsyncCompletedEvent = (s, e) =>
{
// Todo: Extract
downloadDone = true;
};
using (WebClient webClient = new WebClient())
{
webClient.DownloadProgressChanged += DownloadProgressChangedEvent;
webClient.DownloadFileCompleted += AsyncCompletedEvent;
webClient.DownloadFileAsync(downloadLink, saveFilename);
}
while (!downloadDone) ;
return true;
}
}
This is how I use it: 这是我的用法:
(new Installer(startBtn, progressBar, statusLabel)).Start("http://nginx.org/download/nginx-1.9.4.zip");
I am not entirely sure if I have implemented this correctly. 我不确定我是否正确实施了此操作。 Visual studio is giving me the following warning:
Visual Studio向我发出以下警告:
DownloadArchiveAsync - This async method lacks 'await' operators and will run synchronously.
DownloadArchiveAsync-此异步方法缺少“等待”运算符,将同步运行。
Also note; 另请注意; I currently have no proper way of detecting when the download is completed, so I am using
bool
and a while
loop - not sure if this is recommended also. 我目前没有检测下载完成时间的正确方法,因此我正在使用
bool
和while
循环-不确定是否也建议这样做。
What is the correct way to use async/await to asynchronously download a zip file and report progress? 使用async / await异步下载zip文件并报告进度的正确方法是什么?
EDIT 编辑
After digging around, I found one possible solution to this. 深入研究之后,我找到了一种可能的解决方案。 I've implemented this method:
我已经实现了这种方法:
async Task IsDownloadDone()
{
await Task.Run(() =>
{
while (!downloadDone) ;
});
}
and updated the DownloadArchiveAsync
return like this: 并更新了
DownloadArchiveAsync
返回,如下所示:
await IsDownloadDone();
return true;
Complete code now looks like this: http://pastebin.com/MuW0386K 现在完整的代码如下所示: http : //pastebin.com/MuW0386K
Is this the correct way to implement this? 这是实现此目标的正确方法吗?
You can replace DownloadArchiveAsync
with something like this, and it will actually work asynchronously: 您可以将
DownloadArchiveAsync
替换为以下内容,它实际上将异步运行:
async Task<bool> DownloadArchiveAsync( string fileUrl )
{
var downloadLink = new Uri( fileUrl );
var saveFilename = System.IO.Path.GetFileName( downloadLink.AbsolutePath );
DownloadProgressChangedEventHandler DownloadProgressChangedEvent = ( s, e ) =>
{
progressBar.BeginInvoke( (Action)(() =>
{
progressBar.Value = e.ProgressPercentage;
}) );
var downloadProgress = string.Format( "{0} MB / {1} MB",
(e.BytesReceived / 1024d / 1024d).ToString( "0.00" ),
(e.TotalBytesToReceive / 1024d / 1024d).ToString( "0.00" ) );
statusLabel.BeginInvoke( (Action)(() =>
{
statusLabel.Text = "Downloading " + downloadProgress + " ...";
}) );
};
using (WebClient webClient = new WebClient())
{
webClient.DownloadProgressChanged += DownloadProgressChangedEvent;
await webClient.DownloadFileTaskAsync( downloadLink, saveFilename );
}
return true;
}
Edit: I found DownloadFileTaskAsync
in the MSDN, makes things a lot prettier. 编辑:我在MSDN中找到
DownloadFileTaskAsync
,这使事情变得更漂亮了。
async
on the method means this method uses await . 方法上的
async
表示此方法使用await 。 So use the awaitable function in 'WebClient'. 因此,请使用“ WebClient”中的等待功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.