Eric J.
Eric J.

Reputation: 150238

WebClient DownloadProgressChangedEventHandler Not Firing

I'm having trouble getting DownloadProgressChangedEventHandler to fire. I understand that, worst case, the event handler should fire every 64Kb. The URL I'm trying to download data from creates 680Kb of XML data on the fly, but the handler does not fire at all.

Here's test code that demonstrates the problem. Unfortunately I cannot share the specific URL as it contains proprietary data.

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

Upvotes: 0

Views: 3634

Answers (2)

Eric J.
Eric J.

Reputation: 150238

My code was structured so that the WebClient was already used on a non-UI thread, so I extended WebClient to allow for a synchronous call to get events. I also extended it to allow for a custom connection timeout (I was calling a web service that could take quite a while to respond). The new method DownloadFileWithEvents internally calls DownloadFileAsync and properly blocks until the appropriate complete event is received.

Here's the code in case it's useful to anyone:

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

Upvotes: 3

Alexei Levenkov
Alexei Levenkov

Reputation: 100630

Your code looks ok, but documentation says "This event is raised each time an asynchronous download makes progress" while you are using synchronous version of the download. Switch to use DownloadFileAsync.

Upvotes: 4

Related Questions