1

別のスレッドで行われているダウンロードの進行状況を追跡したいと思います。System.Net.WebClient に DownloadStringAsync メソッドがあることは知っていますが、新しい TPL タイプ (TaskFactory、Task など) では直接動作しません。

  • HttpRequest クラスと HttpResponse クラスを使用して進行状況を追跡できますか?
  • 進捗状況を追跡するのに最適なクラスは何ですか? オーバーヘッドが少ないほど良い。
  • 応答のサイズが不明な場合、つまり進行状況を追跡できない場合はありますか?
  • 進捗が発生するたびに UI スレッドと同期する最良の方法は何ですか?

ほとんどの例は、タスク全体が完了した後にのみ UI を更新するタスクを示しています。これらの例では、UI 同期コンテキストを取得する継続を使用して、Dispatcher を直接操作する必要がないようにしています。

アイデアは、進行状況バーを含むすべてのダウンロードを (WPF で) グリッド ビューで表示することです。新しい行を追加し、進行状況バーを常に更新します。このコードが混乱するのを避けようとしています。

4

1 に答える 1

3

DownloadStringAsync とその他のイベント メソッドは、.NET 4.0 の TPL とうまく連携します (EAP と TPL を確認してください)。一般に、TPL は TaskCompletionSource を介したイベント非同期プログラミングをサポートします。Begin/EndXXX モデル (APM) は、Task.FromAsync メソッドによってサポートされます。詳細な説明TPL and Traditional .NET Asynchronous Programmingを見つけることができます。

ParallelExtensionExtrasライブラリには、適切なイベントが発生したときに完了するタスクを返す DownloadStringTask などの一連の WebClient 拡張メソッドがあります。

次のコードは、ダウンロードが完了すると完了するタスクを作成します。

    public Task<string> DownloadStringTask(WebClient client,Uri uri)
    {
        var tcs = new TaskCompletionSource<string>();
        client.DownloadStringCompleted += (o, a) => tcs.SetResult(a.Result);
        client.DownloadStringAsync(uri);
        return tcs.Task;
    }

UI の更新に関しては、DownloadProgressChanged イベントを使用して簡単にフィードバックを提供できます。

using (var client = new WebClient())
{
    client.DownloadProgressChanged += (o, a) => Console.WriteLine("{0}",a.ProgressPercentage);

    var task = DownloadStringTask(client,new Uri("http://www.stackoverflow.com"));
    var write=task.ContinueWith(t => Console.WriteLine("Got {0} chars", t.Result.Length));
    write.Wait();
    Console.ReadKey();
}

データ バインディングを使用して進行状況の値を進行状況バーに提供する場合は、進行状況の値のプロパティを更新するだけです。プログレス バーを直接更新する場合 (良い考えではありません)、プログレス バーのディスパッチャを使用して UI スレッドへの呼び出しをマーシャリングする必要があります。このような

    void UpdateProgress(int percent)
    {
        if (progressBar1.CheckAccess())
            progressBar1.Value = percent;
        else
        {                
            progressBar1.Dispatcher.Invoke(new Action(()=>UpdateProgress(percent)));
        }
    }
    ....
    client.DownloadProgressChanged += (o, a) => UpdateProgress(a.ProgressPercentage);
于 2012-05-25T07:14:29.760 に答える