3

WPF と MVVM を使用して、Web サーバーから大きなファイル (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 アプリケーションであるため、noasyncまたはawait. アプリケーション全体が無反応になり、ウィンドウのサイズ変更、ボタンのクリック、テキストボックスの操作はまったく行われません。

デバッガーに割り込むと、OnPropertyChanged()-Method でハングアップし続け (ほとんどの時間が経過するためだと思います)、次のコール スタックを取得します。

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#

そこにぶら下がっていません。さらに一歩踏み出すと、遅れることなく進みます。

4

1 に答える 1

7

ダウンロードされたバイト数について多くのフィードバックが寄せられているようですが、プロパティ変更イベント ハンドラーは比較的非効率的です。たぶん、更新の頻度を制限する必要がありますBytesReceived-時間 (たとえば、1 秒あたり 5 回更新) またはデルタ (K を超えて変更されたときに更新) またはハイブリッド バージョンのいずれかです。

ただし、プロパティで何が起こっているかを調べたい場合もあります。最適化できる非効率なものがないかどうかを確認してください。

(最初のステップは、呼び出された回数を数えることかもしれませんwebClient_DownloadProgressChanged。)

于 2013-05-31T21:27:09.973 に答える