0

我正在使用带有 CookieContainer 的 Webclient 从 Web 服务(Sharepoint)下载数据。

我想 DownloadDataAsync 以便下载多个文档并在每个文档下载时更新一个进度条。非异步版本 - DownloadData 不发送进度更新。

  1. 在继续下一个文档之前,如何让异步版本在 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();
    }
    

    }

    公共类 CookieAwareWebClient : WebClient { 公共 CookieContainer CookieContainer { 获取;放; }

    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 事件。您可以设置一个 volatile bool 来进行轮询,也可以对事件执行此操作。在性能方面只有微小的差异,但通常事件可能是更清洁的解决方案(我更喜欢布尔轮询)。在您的情况下,您可能实际上希望在 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 回答