WebClient DownloadProgressChangedEventHandler未触发

问题描述:

我无法获取DownloadProgressChangedEventHandler触发。我明白,最糟糕的情况是,事件处理程序should fire every 64Kb。我试图从中下载数据的URL在运行中创建了680Kb的XML数据,但处理程序根本不会启动。WebClient DownloadProgressChangedEventHandler未触发

下面是演示问题的测试代码。很遗憾,我无法分享特定的网址,因为它包含专有数据。

static void Main(string[] args) 
{ 
    Console.WriteLine("Downloading data"); 
    string url = "https://MyUrlThatRespondsWith680KbOfData"; 
    string outputPath = @"C:\Temp\DeleteMe.xml"; 
    using (WebClient webClient = new WebClient()) 
    { 
     webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged); 
     webClient.DownloadFile(url, outputPath); 
    } 
    Console.Write("Done"); 
    Console.ReadKey(true); 
} 

static void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
{ 
    Console.WriteLine("Download progress: " + e.BytesReceived); 
} 

你的代码看起来不错,但documentation说,当您使用下载的同步版本“这一事件是每一个异步下载使人进步次上调”。切换到使用DownloadFileAsync

+0

是的,这做到了。 Lame,因为下载已经发生在专用线程上(其后续负责处理下载的数据。 – 2012-03-06 02:08:48

我的代码的结构使WebClient已经用在非UI线程上,所以我扩展了WebClient以允许同步调用来获取事件。我还扩展它以允许自定义连接超时(我正在调用一个可能需要相当长时间才能响应的Web服务)。新方法DownloadFileWithEvents内部调用DownloadFileAsync并正确阻塞,直到收到相应的完整事件。

这里的情况下,它是任何人有用的代码:

public class MyWebClient : WebClient 
{ 
    //time in milliseconds 
    private int timeout; 
    public int Timeout 
    { 
     get 
     { 
      return timeout; 
     } 
     set 
     { 
      timeout = value; 
     } 
    } 

    public MyWebClient(int timeout = 60000) 
    { 
     this.timeout = timeout; 
     this.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(MyWebClient_DownloadFileCompleted); 
    } 

    EventWaitHandle asyncWait = new ManualResetEvent(false); 

    public void DownloadFileWithEvents(string url, string outputPath) 
    { 
     asyncWait.Reset(); 
     Uri uri = new Uri(url); 
     this.DownloadFileAsync(uri, outputPath); 
     asyncWait.WaitOne(); 
    } 

    void MyWebClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 
    { 
     asyncWait.Set(); 
    } 

    protected override WebRequest GetWebRequest(Uri address) 
    {    
     var result = base.GetWebRequest(address); 
     result.Timeout = this.timeout; 
     return result; 
    } 
}