WebClient DownloadProgressChangedEventHandler未触发

时间:2012-03-06 01:33:16

标签: c# webclient

我无法启动DownloadProgressChangedEventHandler。我理解,最坏的情况是事件处理程序should fire every 64Kb。我正在尝试下载数据的URL动态创建680Kb的XML数据,但处理程序根本不会触发。

这是演示此问题的测试代码。不幸的是,我无法共享特定的URL,因为它包含专有数据。

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);
}

2 个答案:

答案 0 :(得分:4)

您的代码看起来没问题,但documentation说“当您使用同步版本的下载时,每次异步下载进行时都会引发此事件”。切换为使用DownloadFileAsync

答案 1 :(得分:3)

我的代码是结构化的,因此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;
    }
}