简体   繁体   中英

Stream.ReadAsync() on first invoke very slow

I am writing a class to handle file downloads and i am using this code [simplified]:

var webRequest = (HttpWebRequest)WebRequest.Create(downloadOperation.Link);
webRequest.Proxy = null;
using (var webResponse = await webRequest.GetResponseAsync())
{
    using (var downloadStream = webResponse.GetResponseStream())
    {
        using (var outputFileWriteStream = await outputFile.OpenStreamForWriteAsync())
        {
            var buffer = new byte[4096];
            var downloadedBytes = 0;
            var totalBytes = webResponse.ContentLength;
            while (downloadedBytes < totalBytes)
            {
                //*************************THIS LINE TAKES ABOUT 32 SECONDS TO EXECUTE ON FIRST INVOKE, ALL NEXT INVOKES TAKE ABOUT 120MS***************************
                var currentRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length);
                //*******************************************************************************************************************************************************************

                await outputFileWriteStream.WriteAsync(buffer, 0, currentRead); 
            }
        }
    }
}

Can you please explain to me why is it taking that long on first invoke and not on the next ones? I am worried that it is downloading the entire file on the first read.

Note that the files are usually between 3~15MB.

I am worried that it is downloading the entire file on the first read.

That's precisely what's happening. You can change that by setting webRequest.AllowReadStreamBuffering to false .

So i found a way to fix this problem, but it doesn't use WebRequest class.

I am now using the HttpClient found in (Windows.Web.Http).

Here is the fixed code:

    var client = new Windows.Web.Http.HttpClient(); // prepare the http client 

//get the response from the server
using (var webResponse = await client.GetAsync(downloadOperation.Link, HttpCompletionOption.ResponseHeadersRead)) //***********Node the HttpCompletionOption.ResponseHeaderRead, this means that the operation completes as soon as the client receives the http headers instead of waiting for the entire response content to be read
{
    using (var downloadStream = (await webResponse.Content.ReadAsInputStreamAsync()).AsStreamForRead() )
    {
        using (var outputFileWriteStream = await outputFile.OpenStreamForWriteAsync())
        {
            var buffer = new byte[4096];
            var downloadedBytes = 0;
            var totalBytes = webResponse.ContentLength;
            while (downloadedBytes < totalBytes)
                {
                    //*************************THIS LINE NO LONGER TAKES A LONG TIME TO PERFORM FIRST READ***************************
                    var currentRead = await downloadStream.ReadAsync(buffer, 0, buffer.Length);
                    //*******************************************************************************************************************************************************************

                    await outputFileWriteStream.WriteAsync(buffer, 0, currentRead); 
                }
        }

    }

}

Hope this will help someone out there ;)

thank you all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM