web-dev-qa-db-ja.com

進行状況バーを使用した非同期ファイルのダウンロード

WebClientダウンロードの進行状況が変化するにつれて、進行状況バーの進行状況を変更しようとしています。 startDownload()を呼び出すと、このコードはまだファイルをダウンロードしますが、ファイルをダウンロードするとウィンドウがフリーズします。スプラッシュ画面が読み込まれると、ユーザーが進行状況の変化を確認できるようにします。ユーザーがprogressBar2変更の進行状況を確認できるように、これを修正する方法はありますか?

private void startDownload()
{
    WebClient client = new WebClient();
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
    client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
    client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    double bytesIn = double.Parse(e.BytesReceived.ToString());
    double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
    double percentage = bytesIn / totalBytes * 100;
    label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
    progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    label2.Text = "Completed";
}
22
Joshua Ferrara

UIスレッドからstartDownload()を呼び出す必要があります。 WebClient.DownloadFileAsync()の全体的な考え方は、呼び出しスレッドをブロックせずに自動的にワーカースレッドを生成するということです。 startDownload()で、UIスレッドによって作成されたと思われるコントロールを変更するコールバックを指定しました。したがって、バックグラウンドスレッドからstartDownload()を呼び出すと、スレッドは作成したUI要素しか変更できないため、問題が発生します。

動作するはずの方法は、UIスレッドからstartDownload()を呼び出し、定義したstartDownload()がUIスレッドによって処理されるイベントコールバックを設定することです。その後、ダウンロードを非同期的に開始し、すぐに戻ります。進行状況が変わるとUIスレッドに通知され、進行状況バーコントロールの更新を担当するコードがUIスレッドで実行されるため、問題は発生しません。

13
Bojin Li

startDownload()をクリックすると、UIスレッドがフリーズします。フォームをフリーズしたくない場合は、別のスレッドでstartDownload()を使用し、クロススレッドで進捗状況を更新します。一方通行、

private void startDownload()
{
    Thread thread = new Thread(() => {
          WebClient client = new WebClient();
          client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
          client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
          client.DownloadFileAsync(new Uri("http://joshua-ferrara.com/luahelper/lua.syn"), @"C:\LUAHelper\Syntax Files\lua.syn");
    });
    thread.Start();
}
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate {
        double bytesIn = double.Parse(e.BytesReceived.ToString());
        double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
        double percentage = bytesIn / totalBytes * 100;
        label2.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
        progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
    });
}
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    this.BeginInvoke((MethodInvoker) delegate {
         label2.Text = "Completed";
    }); 
}

このようなGoogleのマルチスレッドの詳細を読む http://msdn.Microsoft.com/en-us/library/ms951089.aspx

-行方不明の修正); bgThread宣言へ

25
Peter PAD
 public class ProgressEventArgsEx
{
    public int Percentage { get; set; }
    public string Text { get; set; }
}
public async static Task<string> DownloadStraingAsyncronous(string url, IProgress<ProgressEventArgsEx> progress)
{
    WebClient c = new WebClient();
    byte[] buffer = new byte[1024];
    var bytes = 0;
    var all = String.Empty;
    using (var stream = await c.OpenReadTaskAsync(url))
    {
        int total = -1;
        Int32.TryParse(c.ResponseHeaders[HttpRequestHeader.ContentLength], out total);
        for (; ; )
        {
            int len = await stream.ReadAsync(buffer, 0, buffer.Length);
            if (len == 0)
                break;
            string text = c.Encoding.GetString(buffer, 0, len);

            bytes += len;
            all += text;
            if (progress != null)
            {
                var args = new ProgressEventArgsEx();
                args.Percentage = (total <= 0 ? 0 : (100 * bytes) / total);
                progress.Report(args);
            }
        }
    }
    return all;
}
// Sample
private async void Bttn_Click(object sender, RoutedEventArgs e)
{
    //construct Progress<T>, passing ReportProgress as the Action<T> 
    var progressIndicator = new Progress<ProgressEventArgsEx>(ReportProgress);
    await TaskLoader.DownloadStraingAsyncronous(tbx.Text, progressIndicator);
}
private void ReportProgress(ProgressEventArgsEx args)
{
    this.statusText.Text = args.Text + " " + args.Percentage;
}
2
guest

この記事があなたを正しい方向に導くと信じています http://www.dreamincode.net/forums/topic/115491-download-file-asynchronously-with-progressbar/

そして、このMSDN記事で http://msdn.Microsoft.com/en-us/library/ms229675.aspx は、「DoWorkイベントを実行するBackgroundWorkerコンポーネントのワーカースレッドでファイルがダウンロードされる方法」について説明しています。ハンドラ。このスレッドは、コードがRunWorkerAsyncメソッドを呼び出すと開始されます。」

1