2

so I'm using webClient.DownloadFileAsync(url, sFilePathToWriteFileTo); to download a file

Url is string url = "http://localhost/1.zip";

sFilePathToWriteFileTo is root directory

Whenever I download the 500mb zip archive, my label1 goes berserk and says "Downloading with INF kb/s" and that's about when it starts not responding and crashes

label1 is label1.Text = string.Format("Downloading with {0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));

It works perfectly fine when I'm downloading low size files, 20mb-50mb

Oh btw, (I just re-read my post), sw is StopWatch, incase you wonder

What is the problem here, and how can I solve it?

-- Edit, added webClient:

using (webClient = new WebClient())
                {
                    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(wzCompleted);
                    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wzProgressChanged);
                    Uri url = new Uri(sUrlToReadFileFrom);
                    sw.Start();
                    try
                    {
                        webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);
                    }
                    catch (Exception ex)
                    {
                        downloadInfo.Text = ex.Message;
                    }
                }

wzProgressChanged:

private void wzProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        statusContent.Text = "Downloading new game files";
        downloadInfo.Text = "Downloading: " + string.Format("{0} MB / {1} MB", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00")) + " with " + string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")) + " (" + e.ProgressPercentage.ToString() + "%" + ")";
        progressBar1.Value = e.ProgressPercentage;
    }

wzCompleted: It's just enabling 2 buttons and disabling 2 others, no need for this?

Dan Bowell
  • 49
  • 1
  • 4

2 Answers2

0

Do 3 things in your wzProgressChanged handler:

  1. Make sure you marshal the control updates onto the UI thread (assuming it's WinForms use InvokeRequired and Invoke)
  2. Make sure sw.Elapsed.TotalSeconds isn't zero to avoid divide by zero
  3. Wrap the whole body of the handler in a try catch so you can see exceptions your code may be throwing.

Read the documentation about InvokeRequired. It will tell you all about the UI thread and how to make sure you are updating the UI appropriately. I would make the code look something like this (not tested or even compiled but is pretty close)

private void wzProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(() => wzProgressChanged(sender, e));
    }
    else if (sw.Elapsed.TotalSeconds > 0)
    {
        try
        {
            statusContent.Text = "Downloading new game files";
            downloadInfo.Text = "Downloading: " + string.Format("{0} MB / {1} MB", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00")) + " with " + string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")) + " (" + e.ProgressPercentage.ToString() + "%" + ")";
            progressBar1.Value = e.ProgressPercentage;
        }
        catch(Exception e)
        {
            System.Diagnostics.Debug.WriteLine(e.Message);
        }
    }
}
dkackman
  • 15,179
  • 13
  • 69
  • 123
  • How do I do the 2 first things you said? I'm not really an expert at C# I tried wrapping it in a try catch, but the application just stops responding like usual and doesn't write out the caught exception I've tried making it write the exception to a label, a new file with filestreamer, a messagebox, but none of those worked – Dan Bowell May 14 '15 at 03:17
  • I'd bet dollars to donuts that you are updating the UI from a background thread (the web worker thread) so even though you are catching the exception, by putting that exception message on a label your handler is causing the same error and BOOM. Read up on threading and UI updating in WinForms. – dkackman May 14 '15 at 17:56
0

In addition to what dkackman suggested, I'd also suggest being a bit more selective about how often you update your label and maybe put some additional checking around your values to ensure you don't get values line NaN/INF. See other posts here on SO around what they mean exactly. Look at methods like Double.IsInfinity to help you determine if your calc resulted in a number that can be displayed or not.

Also, do some of your calculations outside of your string format statement and based on your findings, you could decide what information to provide to the user.

Community
  • 1
  • 1
Mr Moose
  • 5,946
  • 7
  • 34
  • 69
  • Well, the thing is, I want the users to be notified exactly how much they are downloading, how fast, and their current progress. So limiting that would kind of ruin the point, when I want the opposite. – Dan Bowell May 14 '15 at 03:19
  • I understand that..but if your calculations result in useless information...then it's probably best to withhold that from your users. That was what I was suggesting when I said to be selective about your messges: only provide information your users can understand and appreciate. – Mr Moose May 14 '15 at 03:54