我们目前正在使用HttpClient
下载文件,因为我们的后端需要证书。
我有一个控件 - FileRow
,这是一个带有code-behind
个文件下载方法的UI元素,如下所示:
if (FileIsDownloaded == false)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () =>
{
DataManager.Instance.DownloadFile(this);
});
}
if (ThumbnailIsDownloaded == false)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () =>
{
DataManager.Instance.DownloadThumbnail(this);
});
}
下载单项是好的但是当我点击全部下载(约50项)时,整个UI开始冻结。
正如您所看到的,我试图给予请求低优先级 - 但结果仍然相同。
常见问题的答案:
1)是的,文件应该一次全部下载,而不是一个接一个地下载
2)DataManager.Instance.DownloadThumbnail(this)
- 我这样做是为了对当前控制进行参考,以便我可以在进度条中报告进度。
有什么建议吗?
修改
下载如下:
public async void DownloadFile(FileRow fileRow)
{
//Lot of checking for if file exist, if version is the same
string LocalFilename = await DownloadManager.DownloadFile(fileRow.MyFile.file.id, fileRow.MyFile.file.version, fileRow.MyFile.file.filename,fileRow);
// next is just using the filename string
}
最后我的下载:
public static async Task<string> DownloadFileOfCustomerAssetRow(int? id, int? version, string filename, FileRow fileRow)
{
try
{
HttpClientHandler aHandler = new HttpClientHandler();
aHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
HttpClient aClient = new HttpClient(aHandler);
customerAssetRow.CurrentFileDownload = aClient;
aClient.DefaultRequestHeaders.ExpectContinue = false;
HttpResponseMessage response = await aClient.GetAsync(WebServices.BackendStartUrl + "getFileData?id=" + id + "&version=" + version, HttpCompletionOption.ResponseHeadersRead);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.GenerateUniqueName);
fileRow.FileName = file.Name;
using (var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
{
Stream stream = await response.Content.ReadAsStreamAsync();
IInputStream inputStream = stream.AsInputStream();
ulong totalBytesRead = 0;
while (true)
{
IBuffer buffer = new Windows.Storage.Streams.Buffer(1024);
buffer = await inputStream.ReadAsync(
buffer,
buffer.Capacity,
InputStreamOptions.None);
if (buffer.Length == 0)
{
break;
}
totalBytesRead += buffer.Length;
fileRow.Progress.Value = fileRow.Progress.Value + 1024;
await fs.WriteAsync(buffer);
}
inputStream.Dispose();
}
fileRow.Progress.Visibility = Visibility.Collapsed;
return file.Name;
}
catch (Exception e)
{
ErrorReporter.ReportError("Error in DownloadManager.cs in function DownloadFile.", e);
return "";
}
}
答案 0 :(得分:0)
您的async
方法延续可能会过多地中断UI线程。尝试通过介绍DownloadFileOfCustomerAssetRow
报告者,在背景逻辑(FileRow
)和用户界面(IProgress<T>
)之间建立更强的分离。然后确保背景逻辑中的每个await
都有ConfigureAwait(false)
。
public static async Task<string> DownloadFileOfCustomerAssetRow(int? id, int? version, string filename, IProgress<int> progress)
{
HttpClientHandler aHandler = new HttpClientHandler();
aHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
HttpClient aClient = new HttpClient(aHandler);
customerAssetRow.CurrentFileDownload = aClient;
aClient.DefaultRequestHeaders.ExpectContinue = false;
HttpResponseMessage response = await aClient.GetAsync(WebServices.BackendStartUrl + "getFileData?id=" + id + "&version=" + version, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.GenerateUniqueName).ConfigureAwait(false);
fileRow.FileName = file.Name;
using (var fs = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite).ConfigureAwait(false))
{
Stream stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
IInputStream inputStream = stream.AsInputStream();
ulong totalBytesRead = 0;
while (true)
{
IBuffer buffer = new Windows.Storage.Streams.Buffer(1024);
buffer = await inputStream.ReadAsync(
buffer,
buffer.Capacity,
InputStreamOptions.None).ConfigureAwait(false);
if (buffer.Length == 0)
{
break;
}
totalBytesRead += buffer.Length;
if (progress != null)
progress.Report(totalBytesRead);
await fs.WriteAsync(buffer).ConfigureAwait(false);
}
inputStream.Dispose();
}
return file.Name;
}