【问题标题】:WebClient DownloadFileAsync() blocks threadWebClient DownloadFileAsync() 阻塞线程
【发布时间】:2013-05-31 21:11:28
【问题描述】:

我正在尝试使用 WPF 和 MVVM 从我的网络服务器下载一个大文件 (500 mb)。因此,以下属性都绑定到某种控件(进度条)。问题是,应用程序仍然挂起,即使在使用 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#

它不会挂在那里,当进一步前进时它会毫不拖延地前进。

【问题讨论】:

  • 您能否详细说明“挂起” - 这是完整的作品,根本没有 UI 事件(例如窗口大小调整)得到查看?如果您使用调试器中断会发生什么 - 调用堆栈是什么样的?
  • 你试过让 StartDownload 异步吗?
  • @JonSkeet 我已经编辑了信息,谢谢!

标签: c# wpf mvvm webclient


【解决方案1】:

听起来您收到了很多关于下载字节数的反馈,而属性更改事件处理程序的效率相对较低。也许您应该只限制更新BytesReceived 的频率 - 按时间(例如每秒更新五次)或按增量(当它的更改超过 K 时更新)或某些混合版本。

不过,您可能还想查看属性中发生的情况 - 看看那里是否有任何低效的地方可以优化。

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

【讨论】:

  • 好吧,快速测试(注释掉BytesReceived 的分配)使 UI 保持响应(可能的按钮交互)...我认为这是问题所在,永久 PropertyChanged() 导致了UI 快疯了。谢谢!
猜你喜欢
  • 2015-11-16
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
  • 2016-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多