0

I am implementing a method in order to Download multiple files after each other.

I want the Method to be async so I dont block the UI.

This is the Method to Download a single file and return the Download-Task to the superior Method, which downloads all files (further down).

public Task DownloadFromRepo(String fileName)
        {
            // Aktuellen DateiNamen anzeigen, fileName publishing for Binding
            CurrentFile = fileName;
            // Einen vollqualifizierten Pfad erstellen, gets the path to the file in AppData/TestSoftware/
            String curFilePath = FileSystem.GetAppDataFilePath(fileName);
            // Wenn die Datei auf dem Rechner liegt, wird sie vorher gelöscht / Deletes the file on the hdd
            FileSystem.CleanFile(fileName);
            using (WebClient FileClient = new WebClient())
            {
                FileClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler((s, e) =>
                {
                    Progress++;
                });
                // Wenn der Download abgeschlossen ist.
                FileClient.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler((s, e) =>
                {

                });
                // Den DOwnload starten
                return FileClient.DownloadFileTaskAsync(new System.Uri(RepoDir + fileName), curFilePath);
            }
        }

In here, I just create an IEnumerable<Task> from all the Files in FilesToDownload.

public async void DownloadFiles()
        {
            // Angeben, dass der Download nun aktiv ist / Show active binding
            Active = true;
            // Den Fortschritt zurücksetzen / Set Progress to 0 (restarting download)
            Progress = 0;
            // Die bereits heruntergeladenen Dateien schließen. / Clear Downloads
            DownloadedFiles.Clear();
            // Alle Downloads starten und auf jeden einzelnen warten
            await Task.WhenAll(FilesToDownload.Select(file => DownloadFromRepo(file)));
        }

And finally, I want to call the method like this:

private void RetrieveUpdate()
        {
            UpdateInformationDownload.DownloadFiles();
            AnalyzeFile();
        }

Problem is, that the Method RetrieveUpdate() skips AnalyzeFile() and then tries to access the files, which are being downloaded at the moment..

NEED I want to be able to call UpdateInformationDownload.DownloadFiles(), wait until it completed (that means, it downloaded all the files) and THEN continue in sync with AnalyzeFile().

How can I achieve that? I already looked up plenty of resources on the internet and found several explanations and Microsoft Docs, but I think I didnt step through the scheme of using async/await.

Leon Bohmann
  • 402
  • 1
  • 4
  • 16
  • [`public async void DownloadFiles` is wrong here](https://stackoverflow.com/questions/12144077/async-await-when-to-return-a-task-vs-void) you need `public async Task DownloadFiles` – Liam Sep 25 '18 at 14:49

1 Answers1

7

Simple: await it!

 public aysnc Task DownloadFromRepo(String fileName)
 {
    ...
    using (WebClient FileClient = new WebClient())
    {
        ...
        await FileClient.DownloadFileTaskAsync(new System.Uri(RepoDir + fileName), 
curFilePath);
    }
}

Without the await, indeed: the Dispose() happens immediately.

I believe that roslynator now automatically detects this scenario and warns you about it (and has an auto-fix available) - well worth installing.

Likewise:

private async Task RetrieveUpdate()
{
    await UpdateInformationDownload.DownloadFiles();
    AnalyzeFile();
}

and:

public async Task DownloadFiles() {...}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • If I do it that way, I will always have to call `RetrieveUpdate()` in an async Method? How do I call it in a normal Method? – Leon Bohmann Sep 25 '18 at 14:54
  • @LeonBohmann [How to call asynchronous method from synchronous method in C#?](https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c/25097498), ideally you don't. You make your entire call stack async – Liam Sep 25 '18 at 14:59