问题
I'm trying to download a large file (500 mb) from my webserver using WPF and MVVM. Thus the following properties are all bound to some kind of controls (progressbar). The problem is, that the application still hangs, even while using DownloadFileAsync.
The file is being downloaded as I can tell from my logs (and the file growing, of course).
This is my code:
#region Methods
private void StartDownload(string url, string localPath)
{
Logger.Debug("Starting to initialize file download");
if (!_webClient.IsBusy)
{
_webClient = new WebClient();
_webClient.Proxy = null; // http://stackoverflow.com/questions/754333/why-is-this-webrequest-code-slow/935728#935728
_webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
_webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
_webClient.DownloadFileAsync(new Uri(url), localPath);
}
Logger.Debug("Finished initializing file download");
}
private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
Logger.Debug("Download finished! Cancelled: {0}, Errors: {1} ", e.Cancelled, e.Error);
}
private void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
Logger.Debug("Downloading... Progress: {0} ({1} bytes / {2} bytes)", e.ProgressPercentage, e.BytesReceived, e.TotalBytesToReceive);
if (!IsDownloadPaused)
{
DownloadFileProgress = e.ProgressPercentage;
BytesReceived = e.BytesReceived;
TotalBytesToReceive = e.TotalBytesToReceive;
}
else
{
Logger.Debug("Download paused...");
}
}
#endregion Methods
Edit as per comment request:
It's a .NET 4 CP application, thus no async
or await
. The entire application is going responseless, no window resizing, button clicking or textbox-interaction at all.
When I break in with the debugger, I keep hanging in the OnPropertyChanged()-Method (I think because that's where most of the time goes by) and get the following call stack:
Launcher.exe!Company.Product.Tools.Launcher.ViewModels.ViewModelBase.OnPropertyChanged(string propertyName) Line 16 + 0x59 bytes C#
Launcher.exe!Company.Product.Tools.Launcher.ViewModels.DownloadViewViewModel.BytesReceived.set(long value) Line 82 + 0x21 bytes C#
Launcher.exe!Company.Product.Tools.Launcher.ViewModels.DownloadViewViewModel.webClient_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e) Line 216 + 0x3f bytes C#
It doesn't hang there, when stepping further it goes without any delay.
回答1:
It sounds like you're getting lots of feedback about the number of bytes downloaded, and the property changed event handler is relatively inefficient. Maybe you should only limit how often you update BytesReceived
- either by time (e.g. update it five times per second) or by delta (update it when it's changed by more than a K) or some hybrid version.
You might also want to look into what's happening in the property though - see whether there's anything inefficient there which you could optimize.
(The first step might be to keep a count of just how many times webClient_DownloadProgressChanged
is called.)
来源:https://stackoverflow.com/questions/16866059/webclient-downloadfileasync-blocks-thread