Reputation: 796
I'm currently working on a small Mini-game. The Game has the ability to open some Options, in the Options you can click "Enable Music" for example. Because the Application would be too big including the Audio files, I want the User to choose if he wants Music, and has to Download it, or not.
I'm using an Async-Task for this Option since the Options should Pop-Up while downloading, this is my Code so far:
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:\Users\Public\Documents\Ultimate Tic-Tac-Toe\Audios\"), 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;
}
This downloads one file, but I need two. So I tried to wait for my Progress-Bar to fill, download the next one, and if I have 2 Files, Finish! But the Code jumps right into "DownloadFileCompleted", so that does not work. I'm sitting at this for round about 2 hours now, fiddling around.
How do I get the Async Task to create a "Que" of two files, download them and then jump to "DownloadFileCompleted" and still show the Progress? Thank you!
Upvotes: 1
Views: 3437
Reputation: 30454
Something that might be useful to understand async-await might be Eric Lippert's restaurant metaphor that explains very well why you would like to use async-await and in which cases not. Search somewhere half way the page for the question What's the difference between Asynchrony and Parallelism?
Stephen Cleary explains the basics in this article
The nice thing about async-await is that your program looks sequential and can be read as-if sequential, while in fact as soon as it has to wait for something your thread looks around if it can do something else instead of waiting. In Eric Lippert's restaurant metaphor: instead of waiting until the bread is toasted it starts boiling water to make some tea.
One of the things you forgot to do is to await for the download async. As Stephen Cleary explained, this can only be done if you declare your function async while returning a Task:
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;
}
If you want, you can start the two download simultaneously. This is not always faster:
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;
}
Upvotes: 3