WebClient DownloadProgressChangedEventHandler Not Firing - PullRequest
0 голосов
/ 06 марта 2012

У меня проблемы с запуском DownloadProgressChangedEventHandler.Я понимаю, что в худшем случае обработчик событий должен запускаться каждые 64Kb .URL, с которого я пытаюсь загрузить данные, создает на лету 680 КБ данных 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 ]

4 голосов
/ 06 марта 2012

Ваш код выглядит нормально, но документация говорит: «Это событие вызывается каждый раз, когда выполняется асинхронная загрузка», когда вы используете синхронную версию загрузки.Переключитесь на использование DownloadFileAsync .

3 голосов
/ 19 марта 2012

Мой код был структурирован так, что WebClient уже использовался в потоке без пользовательского интерфейса, поэтому я расширил WebClient, чтобы позволить синхронный вызов для получения событий.Я также расширил его, чтобы учесть время ожидания пользовательского соединения (я звонил в веб-службу, на ответ которой могло потребоваться довольно много времени).Новый метод 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;
    }
}
...