等待DownloadFileAsync完成下载,然后执行某些操作。

3
基本上我的DownloadFile函数是这样的:
public void DownloadFile()
{
    settings_btn.Enabled = false;
    label1.Text = "Checking for updates...";
    //Defines the server's update directory
    string Server = "http://downloadurl/update/";

    //Defines application root
    string Root = AppDomain.CurrentDomain.BaseDirectory;

    //Make sure version file exists
    FileStream fs = null;
    if (!File.Exists("pversion"))
    {
        using (fs = File.Create("pversion")){}
        using (StreamWriter sw = new StreamWriter("pversion")){sw.Write("1.0");}
    }
    //checks client version
    string lclVersion;
    using (StreamReader reader = new StreamReader("pversion"))
    {
        lclVersion = reader.ReadLine();
    }
    decimal localVersion = decimal.Parse(lclVersion);

    //server's list of updates
    XDocument serverXml = XDocument.Load(@Server + "pUpdates.xml");

    //The Update Process
    foreach (XElement update in serverXml.Descendants("pupdate"))
    {
        string version = update.Element("pversion").Value;
        string file = update.Element("pfile").Value;

        decimal serverVersion = decimal.Parse(version);


        string sUrlToReadFileFrom = Server + file;

        string sFilePathToWriteFileTo = Root + file;

        if (serverVersion > localVersion)
        {
            using (webClient = new WebClient())
            {
                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);

                // The variable that will be holding the url address (making sure it starts with http://)
                Uri url = new Uri(sUrlToReadFileFrom);

                // Start the stopwatch which we will be using to calculate the download speed
                sw.Start();

                try
                {
                    // Start downloading the file
                    webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);

                    // Change the currently running executable so it can be overwritten.
                    Process thisprocess = Process.GetCurrentProcess();
                    string me = thisprocess.MainModule.FileName;
                    string bak = me + ".bak";
                    if (File.Exists(bak))
                    {
                        File.Delete(bak);
                    }
                    File.Move(me, bak);
                    File.Copy(bak, me);

                    //unzip
                    using (ZipFile zip = ZipFile.Read(file))
                    {
                        foreach (ZipEntry zipFiles in zip)
                        {
                            zipFiles.Extract(Root + "\\", true);
                        }
                    }

                    //download new version file
                    webClient.DownloadFile(Server + "pversion.txt", @Root + "pversion");

                    //Delete Zip File
                    deleteFile(file);

                    var spawn = Process.Start(me);
                    thisprocess.CloseMainWindow();
                    thisprocess.Close();
                    thisprocess.Dispose();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
}

我的问题是,一旦找到新版本并开始下载文件webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);,它会立即运行下面的代码,即更改名称、解压和下载新版本文件进度。
我想让它在完成文件下载后再执行其余操作。我该怎么做?
-- 如果需要,以下是ProgressChanged:
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    label3.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")) + " " + string.Format("{0} MB's / {1} MB's", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));;
    progressBar1.Value = e.ProgressPercentage;
    label1.Text = e.ProgressPercentage.ToString() + "%";
}

已完成:

private void Completed(object sender, AsyncCompletedEventArgs e)
{
    sw.Reset();
    if (e.Cancelled == true)
    {
        label1.Text = "Download cancelled!";
    }
    else
    {
        label1.Text = "Download completed!";
    }
}

2
所有操作下载的代码都应该移动到“已完成”方法中,这样它只会在下载完成后执行一次。当前,如果下载以同步方式运行,则您的代码仅会等待下载,因为线程将等待。 - DeanOC
你正在使用哪个.NET框架版本? - Massimo Prota
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
1个回答

0
您可以使用DownloadFile方法。Async一词意味着此方法将以异步方式运行(在其他线程中),这就是它几乎立即转到下一行的原因。如果您想等待下载结束,请使用DownloadFile而不是DownloadFileAsync。

这会让用户界面和应用程序在下载时冻结,这是不好的!有许多更好的替代方案。 - Massimo Prota
是的,我注意到了,但是让一个BackgroundWorker运行这个void似乎可以解决冻结的问题^^ - Dan Bowell
11
DownloadFile不会触发进度事件。 - Tejasvi Hegde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接