我想实现一个可重用的类,它将有助于下载给定的zip文件并将其解压缩,同时使用C#5 await / async功能报告进度。
我是新手,现在试图绕过它。到目前为止,这是我的安装程序类:
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;
}
}
这就是我使用它的方式:
(new Installer(startBtn, progressBar, statusLabel)).Start("http://nginx.org/download/nginx-1.9.4.zip");
我不完全确定我是否正确实现了这一点。 Visual Studio给了我以下警告:
DownloadArchiveAsync - 这种异步方法缺乏等待&#39;等待&#39;运营商并将同步运行。
另请注意;我目前没有正确的方法来检测下载何时完成,因此我使用bool
和while
循环 - 不确定是否也推荐这样做。
使用async / await以异步方式下载zip文件并报告进度的正确方法是什么?
修改
在挖掘之后,我找到了一个可能的解决方案。我已经实现了这种方法:
async Task IsDownloadDone()
{
await Task.Run(() =>
{
while (!downloadDone) ;
});
}
并更新了DownloadArchiveAsync
这样的回复:
await IsDownloadDone();
return true;
完整代码现在如下所示:http://pastebin.com/MuW0386K
这是实现这个的正确方法吗?
答案 0 :(得分:3)
你可以用这样的东西替换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;
}
修改:我在MSDN中找到DownloadFileTaskAsync
,让事情变得更漂亮。
async
表示此方法使用等待。因此,请使用WebClient&#39;。