Ramtin
Ramtin

Reputation: 133

App hangs when use HttpWebRequest

i'm using C# to develop an app that download a file from internet (I don't want to use background downloader!) Here is class code for download:

public class DL
{
    public event Progresses OnProgress;
    Stopwatch stopwatch = new Stopwatch();

    public async void Get(string url, StorageFile destinationFile)
    {
        stopwatch.Reset();
        stopwatch.Start();
        HttpWebRequest request = (HttpWebRequest)WebRequest.
            Create(url);
        HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
        long size = response.ContentLength;
        long downloaded = 0;


        using (Stream inputStream = response.GetResponseStream())
        using (Stream outputStream = await destinationFile.OpenStreamForWriteAsync())
        {
            byte[] buffer = new byte[1024];
            int bytesRead;
            do
            {
                bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                downloaded += bytesRead;
                outputStream.Write(buffer, 0, bytesRead);
                int secondsRemaining = (int)(stopwatch.Elapsed.TotalSeconds
                    / downloaded * (size - downloaded));
                TimeSpan span = new TimeSpan(0, 0, 0, secondsRemaining);
                string remainTime = string.Format("{0}:{1}:{2}", span.Hours, span.Minutes, span.Seconds);
                OnProgress(remainTime);
            } while (bytesRead != 0);
        }
    }
}

public delegate void Progresses(string text);

and this is how to download a file:

private async void btnDownload_Click(object sender, RoutedEventArgs e)
{
    DL webGard = new DL();
    webGard.OnProgress += WebGard_OnProgress;
    StorageFile destinationFile = await KnownFolders.MusicLibrary
       .CreateFileAsync("r58.zip", CreationCollisionOption.GenerateUniqueName);
    string url = "my url";
    webGard.Get(url, destinationFile);
}

private async void WebGard_OnProgress(string text)
{
    System.Diagnostics.Debug.WriteLine(text);
    var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
    await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        textBlock.Text = text;
    });
}

When I press download button, app currently goes to hang and can't use it till download ends, I want to show Remaining time to user and this code works on Output windows in visual studio but UI is hanged and can't show results in textBlock.

How can I fix this problem? Thanks

Upvotes: 0

Views: 198

Answers (1)

Shawn Lehner
Shawn Lehner

Reputation: 1323

The issue here is that you are using all of the correct async commands to start, which is great. Unfortunately, when you are actually reading the data from the stream, you are doing this all synchronously. Here is what I mean ...

Once you get your streams initialized, you start reading and writing data using a loop. If you look at your do/while loop you will see that all of the operations are being done synchronously. There are two work items in this loop that is causing your significant app hang. This line:

bytesRead = inputStream.Read(buffer, 0, buffer.Length);

and this line:

outputStream.Write(buffer, 0, bytesRead);

During every iteration of your loop you are going to block your application thread while you wait for a response back from the server with your next chunk of data. This means that not only are you waiting on the server to reply, you are also waiting on the delay to transmit this data over the network. On top of this, you are then being blocked by the file system when you go to write this data back to your file. Instead, you should be using the ReadAsync and WriteAsync methods of the stream.

This way, you are actually only blocking your main thread for a very short amount of time as you actually move the data around in memory. Then you are back to waiting on the streams to finish their operations while your applications UI thread is free to do what it wants.

I hope this helps!

Upvotes: 1

Related Questions