使用AsyncTask下载文件,并在进度栏中显示进度



我目前正在开发一款小型迷你游戏。游戏可以打开一些选项,例如,在选项中可以单击"启用音乐"。因为包括音频文件在内的应用程序太大了,我希望用户选择他是否想要音乐,是否必须下载。

我正在为这个选项使用异步任务,因为选项应该在下载时弹出,这是我迄今为止的代码:

        public void CheckForFiles()
    {
        // searches the current directory and sub directory
        int fCount = Directory.GetFiles(path, "*", SearchOption.AllDirectories).Length;
        //If there are NOT all of the Audiofiles, delete all of them and re-download!
        if (fCount != 2)
        {
            //Just to be sure, delete all previous files!
            Array.ForEach(Directory.GetFiles(@"C:UsersPublicDocumentsUltimate Tic-Tac-ToeAudios"), File.Delete);
            //Change the Button from "Apply" to "Download"
            apply_options.Text = "Download";
            //Set the Warning Text
            warning_text.Text = "Warning! Downloading the needed Audiofiles. DO NOT interrupt the Proccess!";
            //SHow the Download-Progress Bar
            download_progress.Visible = true;
            //Download all
            WebClient webClient = new WebClient();
            webClient.DownloadProgressChanged += (s, y) =>
            {
                download_progress.Value = y.ProgressPercentage;
            };
            webClient.DownloadFileCompleted += (s, y) =>
            {
                download_progress.Visible = false;
                warning_text.Text = "Complete!";
                CheckForFiles();
            };
            webClient.DownloadFileAsync(new Uri(remoteUri_dark), fileName_dark);
            //Text = "Downloading File one of" + WAITLIST;
        }

这下载了一个文件,但我需要两个。所以我试着等待我的进度条填满,下载下一个,如果我有2个文件,完成!但是代码直接跳转到"DownloadFileCompleted",所以这是不起作用的。我在这里坐了大约两个小时,到处乱弄。

我如何让异步任务创建一个由两个文件组成的"Que",下载它们,然后跳到"DownloadFileCompleted"并仍然显示进度?非常感谢。

理解异步等待可能有用的东西可能是Eric Lippert的餐厅比喻,它很好地解释了为什么要使用异步等待,以及在哪些情况下不使用。在页面中间的某个地方搜索问题异步和并行之间有什么区别

Stephen Cleary在这篇文章中解释了的基本原理

异步等待的好处是,你的程序看起来是顺序的,可以像顺序的一样读取,而事实上,一旦它必须等待某个东西,你的线程就会四处寻找,如果它可以做其他事情而不是等待。在埃里克·利珀特的餐厅比喻中:与其等到面包烤好,不如开始烧水泡茶。

您忘记做的一件事就是等待异步下载。正如Stephen Cleary所解释的,只有当您在返回Task时声明函数async时,才能做到这一点:

public async Task CheckForFiles()
{
    // let your thread do all the things sequentially, until it has to wait for something
    // you don't need the events, just await for the DownloadAsync to complete
    download_progress.Visible = true;
    //Download all
    WebClient webClient = new WebClient();
    await webClient.DownloadFileAsync(new Uri(remoteUri_dark), fileName_dark);
    // if here, you know the first download is finished
    ShowProgressFirstFileDownloaded();
    await webClient.DownloadFileAsync( /* 2nd file */);
    // if here: 2nd file downloaded
    ShowProgess2ndFileDownLoaded();
    download_progress.Visible = false;
}

如果您愿意,您可以同时启动这两个下载。这并不总是更快:

public async Task CheckForFiles()
{
     ... do the preparations
    //Download all
    download_progress.Visible = true;
    WebClient webClient = new WebClient();
    var taskDownload1 =  webClient.DownloadFileAsync(/* params 1st file */);
    // do not await yet, start downloading the 2nd file
    var taskDownload2 = webClient.DownloadFileAsync( /* params 2nd file */);
    // still do not await, first show the progress
    ShowProgessDownloadStarted();
    // now you have nothing useful to do, await until both are finished:
    await Task.WhenAll(new Task[] {taskDownload1, taskDownload2});
    // if here, both tasks finished, so:
    download_progress.Visible = false;
}

最新更新