WebClient DownloadFileAsync() blocks thread

守給你的承諾、 提交于 2019-12-07 14:47:31

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!