为什么要下载大文件,但挂起UI线程?

时间:2016-09-26 07:18:28

标签: c# events asynchronous delegates async-await

static async void DownloadData(TextBox textboxURL, TextBlock outputView)
{
    try
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(textboxURL.Text);
            client.Timeout = TimeSpan.FromMinutes(1);

            var request = new HttpRequestMessage(HttpMethod.Get, textboxURL.Text);

            /// Fixed thanks to: http://stackoverflow.com/questions/18720435/httpclient-buffer-size-limit-exceeded
            HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
            /// Version = response.Version.ToString();
            response.EnsureSuccessStatusCode();
            // Result = await response.Content.ReadAsStringAsync();
            // Task<Stream> inputStream = response.Content.ReadAsStreamAsync();

            /// DUPE CODE: var sendTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
            /// NEED TO READ UP ON THIS: response..Result.EnsureSuccessStatusCode();
            var httpStream = await response.Content.ReadAsStreamAsync();

            var picker = new FileSavePicker()
            {
                SuggestedStartLocation = PickerLocationId.Downloads,
                SuggestedFileName = "DOWNLOADING.BIN"
            };

            picker.FileTypeChoices.Add("Any", new List<string>() { "." });
            /// picker.FileTypeChoices.Add("Any", new List<string>() { "*" });

            StorageFile storageFile = await picker.PickSaveFileAsync();

            // Woohoo!  Got it working using await, and removing the Task<> wrapper!
            using (var reader = new StreamReader(httpStream))
            {
                Stream fileStream = await storageFile.OpenStreamForWriteAsync();

                httpStream.CopyTo(fileStream);
                fileStream.Flush();
            }
        }
    }
    catch (Exception ex)
    {
        outputView.Text = "Error, try again!";
        var dlg = new Windows.UI.Popups.MessageDialog(ex.Message, "Error");
        await dlg.ShowAsync();
    }
}

1 个答案:

答案 0 :(得分:5)

您在此处使用同步Stream.CopyTo方法:

httpStream.CopyTo(fileStream);

我想你只是想:

await httpStream.CopyToAsync(fileStream);

但是,您还应删除StreamReader部分 - 您使用 StreamReader,并且它可能会尝试读取一些数据以检测编码。但是,您应该对存储文件使用using语句。所以基本上,改变这个:

using (var reader = new StreamReader(httpStream))
{
    Stream fileStream = await storageFile.OpenStreamForWriteAsync();

    httpStream.CopyTo(fileStream);
    fileStream.Flush();
}

为:

using (Stream fileStream = await storageFile.OpenStreamForWriteAsync())
{
    await httpStream.CopyToAsync(fileStream);
}