WebClient DownloadFileAsync()阻塞线程

本文关键字:线程 DownloadFileAsync WebClient | 更新日期: 2023-09-27 18:16:15

我正在尝试使用WPF和MVVM从我的web服务器下载一个大文件(500 mb)。因此,以下属性都绑定到某种控件(progressbar)。问题是,即使在使用DownloadFileAsync时,应用程序仍然挂起。

文件正在下载,我可以从我的日志中看出(当然,文件正在增长)。

这是我的代码:

    #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

根据评论请求编辑:它是一个。net 4 CP应用程序,因此没有asyncawait。整个应用程序是无响应的,没有窗口大小调整,按钮点击或文本框交互。

当我进入调试器时,我一直挂在OnPropertyChanged()方法中(我认为因为这是大多数时间过去的地方),并获得以下调用堆栈:

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#

它不挂在那里,当进一步时,它没有任何延迟。

WebClient DownloadFileAsync()阻塞线程

听起来您得到了大量关于下载字节数的反馈,并且属性更改事件处理程序的效率相对较低。也许你应该只限制你更新BytesReceived的频率——要么按时间(例如每秒更新五次),要么按增量(当它的变化超过K时更新),或者一些混合版本。

你可能还想看看属性中发生了什么——看看是否有什么低效的地方可以优化。

(第一步可能是记录webClient_DownloadProgressChanged被调用的次数)