下载,使用带有进度报告的Async / Await提取zip文件

本文关键字:Async Await 提取 文件 zip 报告 下载 | 更新日期: 2023-09-27 18:10:17

我想实现一个可重用的类,它将有助于下载给定的zip文件并提取它,同时使用c# 5的await/async特性报告进度。

这是我的新,并试图把我的头围绕它的时刻。这是目前为止我的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;
    }
}

我是这样使用的:

(new Installer(startBtn, progressBar, statusLabel)).Start("http://nginx.org/download/nginx-1.9.4.zip");

我不完全确定我是否正确地实现了这一点。Visual studio给了我以下警告:

DownloadArchiveAsync -这个async方法缺少'await'操作符,将同步运行。

还要注意;我目前没有适当的方法来检测何时下载完成,所以我使用boolwhile循环-不确定这是否也被推荐。

使用async/await异步下载zip文件并报告进度的正确方法是什么?


编辑

经过一番研究,我找到了一个可能的解决方案。我已经实现了这个方法:

async Task IsDownloadDone()
{
    await Task.Run(() =>
    {
        while (!downloadDone) ;
    });
}

和更新DownloadArchiveAsync返回如下:

await IsDownloadDone();
return true;

完整的代码如下所示:http://pastebin.com/MuW0386K

这是实现这个的正确方法吗?

下载,使用带有进度报告的Async / Await提取zip文件

您可以将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在方法上意味着这个方法使用await。所以使用'WebClient'中的await函数