question

Nedudale-0390 avatar image
0 Votes"
Nedudale-0390 asked Paul-5034 commented

How can I wait in form1 to the first file to be downloaded in a class before continue to the rest of the code in form1 ?

In a class I'm downloading a file and if the file is not downloaded fine with error it will try to download it again and if it's fine it will do something else :

 using (System.Net.WebClient wc = new System.Net.WebClient())
             {
                 wc.DownloadFileAsync(new Uri(currentLink), folders[0] + "\\image0.gif");
    
                 wc.DownloadFileCompleted += (s, e) =>
                 {
                     if (e.Error != null)
                     {       
                             current = current.AddMinutes(-5);
                             ct = current.ToString("yyyyMMddHHmm");
                             currentLink = defaultlink + ct + ".gif";
                             wc.DownloadFileAsync(new Uri(currentLink), folders[0] + "\\image0.gif");
                     }
                     else
                     {
                         workingFirstDateTime = current;
    
                         GenerateRadarLinks();
                     }
                 };
             }


In Form1 when I click the button to start downloading I'm calling this method :

 private void btnStart_Click(object sender, EventArgs e)
         {
             dates = new List<DateTime>();
             datesonimages = new List<string>();
    
             btnRadarPath.Enabled = false;
             btnSatellitePath.Enabled = false;
    
             timeCounter1._timer.Enabled = true;
             DownloadImages();
         }
    
         public async void DownloadImages()
         {
             CreateDownloadFolders();
    
             urls = new List<string>();
    
             lblStatus.Text = "Downloading...";
    
             rad.GetRadarImages();
             await Task.Delay(15000);
             foreach (string link in rad.links)
             {
                 urls.Add(link);
             }
    
             await sat.DownloadSatelliteAsync();
             foreach (string link in sat.SatelliteUrls())
             {
                 urls.Add(link);
             }
    
             urlsCounter = urls.Count;
    
             await DownloadAsync();
         }

And in the DownloadImages method I'm using this line to wait for the class to build the links I'm waiting until the first file will be downloading fine without errors then it's building links then I'm adding the links from the class to the urls List

 await Task.Delay(15000);

So I'm waiting 15 seconds. In most of the cases it's working because the first file is downloading successfully before 15 seconds but this is not a real solution not a logic solution. Who said it will take 15 seconds until the file to be downloaded fine without error ? Maybe it will try to download the file for a minute or 5 seconds.

I mean 15 seconds is enough but it's not a solution. it's more kind of workaround.

I wonder if there is a better way to wait in form1 before continue ?

dotnet-csharpwindows-forms
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

Paul-5034 avatar image
0 Votes"
Paul-5034 answered Paul-5034 commented

Is there a reason why you're using DownloadFileAsync over DownloadFileTaskAsync? If you use the latter then you get the benefit of your code inside GetRadarImages flowing more sequentially & typically means it's easier to read/reason about:

public async Task GetRadarImages() {
    using (System.Net.WebClient wc = new System.Net.WebClient()) {
        try {
            await wc.DownloadFileTaskAsync(new Uri(currentLink), folders[0] + "\\image0.gif");

            workingFirstDateTime = current;

            GenerateRadarLinks();
        } catch (Exception) {
            current = current.AddMinutes(-5);
            ct = current.ToString("yyyyMMddHHmm");
            currentLink = defaultlink + ct + ".gif";

            await wc.DownloadFileTaskAsync(new Uri(currentLink), folders[0] + "\\image0.gif");
        }
    }
}


The second benefit is that your DownloadImages method can just await the call to GetRadarImages because it now returns a Task:

await rad.GetRadarImages();
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Not working.

The method :

 public async Task GetRadarImages()
         {
             defaultlink = "https://Radar_";
             current = RoundDown(DateTime.Now, TimeSpan.FromMinutes(-5));
             var ct = current.ToString("yyyyMMddHHmm");
             currentLink = defaultlink + ct + ".gif";
    
             using (System.Net.WebClient wc = new System.Net.WebClient())
             {
                 try
                 {
                     await wc.DownloadFileTaskAsync(new Uri(currentLink), folders[0] + "\\image0.gif");
                     workingFirstDateTime = current;
                     GenerateRadarLinks();
                 }
                 catch (Exception)
                 {
                     current = current.AddMinutes(-5);
                     ct = current.ToString("yyyyMMddHHmm");
                     currentLink = defaultlink + ct + ".gif";
                     await wc.DownloadFileTaskAsync(new Uri(currentLink), folders[0] + "\\image0.gif");
                 }
             }
         }




0 Votes 0 ·

I put a breakpoints on await wc.DownloadFileTaskAsync(new Uri(currentLink), folders[0] + "\\image0.gif"); and GenerateRadarLinks(); and await wc.DownloadFileTaskAsync(new Uri(currentLink), folders[0] + "\\image0.gif");

but it's never get to the GenerateRadarLinks(); once it throw 404 not found and throw exception and didn't try to download again even if it's got to the second download line.


and once it's got to form1 when the file downloaded fine

 await rad.GetRadarImages();
             foreach (string link in rad.links)
             {
                 urls.Add(link);
             }

but rad.links is empty no links at all because it's never reached GenerateRadarLinks(); even if the file was downloaded correctly.


0 Votes 0 ·

If it's common that these downloads produce 404s then you'll likely want to call GetRadarImages inside your catch block instead of the DownloadFileTaskAsync call. At the moment if your download retry fails after the initial attempt and it fails again it'll just throw another exception.

Inside the catch block you're also reducing the current time by 5 minutes so if you choose to call GetRadarImages inside your catch block then you'll probably want to move this line from the top of your GetRadarImages method to avoid getting stuck in an infinite loop when you encounter a 404:

current = RoundDown(DateTime.Now, TimeSpan.FromMinutes(-5));


Alternatively a simpler approach that doesn't rely on recursion would be to just put this logic inside a while(true) loop and only break once the DownloadFileTaskAsync call has passed and didn't throw an exception.

0 Votes 0 ·