Defina o tempo limite para webClient.DownloadFile ()

92

Estou usando webClient.DownloadFile()para baixar um arquivo, posso definir um tempo limite para isso, de modo que não demore tanto se não puder acessar o arquivo?

UnkwnTech
fonte

Respostas:

42

Experimente WebClient.DownloadFileAsync(). Você pode ligar CancelAsync()por cronômetro com seu próprio tempo limite.

Abatishchev
fonte
2
Não quero usar cronômetro ou cronômetro. Eu quero algum hack interno ou abordagem de API. Usar o temporizador / cronômetro me custa um thread adicional para assistir, embora esse recurso talvez já
@Kilanny: então vá com a solução de outra resposta. Ou use HttpClient e defina a propriedade Timeout. Observe também que esta resposta é de 2009.
abatishchev
8
no .Net 4.5+ você também pode usar var taskDownload = client.DownloadFileTaskAsync(new Uri("http://localhost/folder"),"filename")e entãotaskDownload.Wait(TimeSpan.FromSeconds(5));
itsho
257

Minha resposta vem daqui

Você pode criar uma classe derivada, que definirá a propriedade de tempo limite da WebRequestclasse base :

using System;
using System.Net;

public class WebDownload : WebClient
{
    /// <summary>
    /// Time in milliseconds
    /// </summary>
    public int Timeout { get; set; }

    public WebDownload() : this(60000) { }

    public WebDownload(int timeout)
    {
        this.Timeout = timeout;
    }

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        if (request != null)
        {
            request.Timeout = this.Timeout;
        }
        return request;
    }
}

e você pode usá-lo como a classe WebClient base.

Beniamin
fonte
3
No caso de outra pessoa encontrar este código útil, eu tive que definir o tempo limite antes de chamar a base.GetWebRequest (endereço)
Darthtong
Resharper reclama sobre um possível valor nulo para "resultado" e sugere uma verificação nula antes de definir o valor de tempo limite para o WebRequest. Olhando para o código descompilado, parece impossível, a menos que você forneça um WebRequestModules personalizado em seu web.config, mas para uma resposta tão votada, eu adicionaria apenas no caso.
Kevin Coulombe
Estou recebendo o erro nesta linha request.Timeout. Mensagem de erro 'System.Net.WebRequest' does not contain a definition for 'Timeout' and no extension method 'Timeout' accepting a first argument of type 'System.Net.WebRequest' could be found (are you missing a using directive or an assembly reference?) , o que estou perdendo?
Eric
1
@Eric: adicionei usingdiretivas que são usadas por este trecho de código.
Beniamin
1
@titol: use HttpClient em vez de WebClient.
abatishchev
3

Supondo que você queira fazer isso de forma síncrona, usando o método WebClient.OpenRead (...) e definindo o tempo limite no Stream que ele retorna, você obterá o resultado desejado:

using (var webClient = new WebClient())
using (var stream = webClient.OpenRead(streamingUri))
{
     if (stream != null)
     {
          stream.ReadTimeout = Timeout.Infinite;
          using (var reader = new StreamReader(stream, Encoding.UTF8, false))
          {
               string line;
               while ((line = reader.ReadLine()) != null)
               {
                    if (line != String.Empty)
                    {
                        Console.WriteLine("Count {0}", count++);
                    }
                    Console.WriteLine(line);
               }
          }
     }
}

Derivar de WebClient e substituir GetWebRequest (...) para definir o tempo limite sugerido por @Beniamin não funcionou para mim, mas funcionou.

Jeffrymorris
fonte
@jeffymorris não funcionou para mim. Ainda recebo o WebException dizendo "a solicitação foi abortada - a operação atingiu o tempo limite", mesmo se eu especificar stream.ReadTimeoutmaior do que realmente demorou para executar a solicitação
chester89
@jeffymoris por outro lado, a solução com a subclasse webclient também não funcionou, então é provavelmente um problema no lado do servidor
chester89