0

CookieContainer を備えた Webclient を使用して、Web サービス (Sharepoint) からデータをダウンロードしています。

DownloadDataAsync を使用して、複数のドキュメントをダウンロードし、ダウンロード時にドキュメントごとに 1 つのプログレス バーを更新したいと考えています。非非同期バージョン - DownloadData は進行状況の更新を送信しません。

  1. 次のドキュメントに移動する前に、Async バージョンを doc.BinaryData = xx 行で待機させるにはどうすればよいですか?
  2. DownloadFileCompleted イベントからバイト配列を取得するにはどうすればよいですか?
  3. DoEvents を使用せずにプログレスバーに変更を適用するにはどうすればよいですか?

    部分クラス Form() { void Main() { List urls= new List(); //urls.Add("xxxxxxx"); //どこかから取得

        for (int i = 0; i < urls.Count; i++)
        {
            var doc = new Document();
            doc.BinaryData = DocumentAsArray(urls.ElementAt(i));
            entities.AddToDocument(doc);
        }
    }
    
    public byte[] DocumentAsArray(string URL)
    {
        byte[] @return = null;
        using (CookieAwareWebClient client = new CookieAwareWebClient())
        {
            client.CookieContainer = spAuthentication.CookieContainer;
    
            // Assign the events to capture the progress percentage
            client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
    
            client.DownloadDataAsync(new Uri(URL));
        }
    
        return @return;
    }
    
    void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        progressBarControlFile.Position = e.ProgressPercentage;
        var newPc = string.Format("Downloaded {0} %", e.ProgressPercentage);
    
        labelControlFile.Text = newPc;
        Application.DoEvents();
    }
    
    void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
    {
        progressBarControlFile.Position = progressBarControlFile.Properties.Maximum;
        labelControlFile.Text = string.Format("{0} %", progressBarControlFile.Properties.Maximum);
    
        Application.DoEvents();
    }
    

    }

    public class CookieAwareWebClient : WebClient { public CookieContainer CookieContainer { get; 設定; }

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
    
        var webRequest = request as HttpWebRequest;
        if (webRequest != null)
        {
            webRequest.CookieContainer = this.CookieContainer;
            webRequest.KeepAlive = false;
        }
    
        return request;
    }
    

    } }

4

1 に答える 1

1
  1. DownloadFileCompleted イベントを待つ必要があります。ポーリングする揮発性ブールを設定するか、イベントでこれを行うことができます。パフォーマンスに関してはわずかな違いしかありませんが、一般的にはおそらくイベントの方がクリーンな解決策です (私は bool-polling を好みます)。あなたのケースでは、これが DocumentAsArray の最後で実際に起こるのを待ちたいかもしれません。
  2. http://msdn.microsoft.com/en-us/library/ms144190.aspxダウンロードされたデータは Result プロパティで利用できます。
  3. DoEvents メソッドがわかりません。あなたが何をしたいのかを正しく理解していれば、UI を更新したいですか? InvokeEx を呼び出す必要があります (少なくともそれが最も簡単で.. 私が知っている唯一の方法です)。この素晴らしい :) 記事http://www.andreas-reiff.de/2011/06/accessing-a-winformwpf-control-from-another-thread-through-invoke/を見てください。または、stackoverflow にとどまり、クロススレッド コードを呼び出すための最良の方法を参照してください。.

要約すると、非同期で進行状況の更新を取得したいだけの場合は、DocumentAsArray 関数を変更して、1 で説明した DownloadFileCompleted イベントを待機するだけです。その後、UI を呼び出さないように注意するだけです。別のスレッドからのコード - Debug で例外が発生し、そうしないように指示されます (Release では正常に動作します - ほとんどの場合)。したがって、InvokeEx 呼び出しを使用します。

于 2012-05-17T12:42:24.480 に答える