Establecer tiempo de espera para webClient.DownloadFile ()

92

Estoy usando webClient.DownloadFile()para descargar un archivo, ¿puedo establecer un tiempo de espera para esto para que no tome tanto tiempo si no puede acceder al archivo?

UnkwnTech
fuente

Respuestas:

42

Prueba WebClient.DownloadFileAsync(). Puede llamar CancelAsync()por temporizador con su propio tiempo de espera.

abatishchev
fuente
2
No quiero usar temporizador ni cronómetro. Quiero un enfoque integrado de hack o api. Utilizar el temporizador / cronómetro me cuesta hilo adicional para la observación, mientras que esta característica puede que ya se han aplicado, así que por qué reinventar la rueda
@Kilanny: luego ve con la solución de otra respuesta. O use HttpClient y establezca la propiedad Timeout. También tenga en cuenta que esta respuesta es de 2009.
abatishchev
8
en .Net 4.5+ también puede usar var taskDownload = client.DownloadFileTaskAsync(new Uri("http://localhost/folder"),"filename")y luegotaskDownload.Wait(TimeSpan.FromSeconds(5));
itsho
257

Mi respuesta viene de aqui

Puede crear una clase derivada, que establecerá la propiedad de tiempo de espera de la WebRequestclase 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;
    }
}

y puede usarlo como la clase base de WebClient.

Beniamin
fuente
3
En caso de que alguien más se encuentre con este código útil, tuve que establecer el tiempo de espera antes de llamar a la base. GetWebRequest (dirección)
Darthtong
Resharper se queja de un posible valor nulo para "resultado" y sugiere una comprobación nula antes de establecer el valor de Tiempo de espera en WebRequest. Mirando el código descompilado, parece imposible a menos que proporcione un WebRequestModules personalizado en su web.config, pero para una respuesta tan votada, la agregaría por si acaso.
Kevin Coulombe
Recibo el error en esta línea request.Timeout. Mensaje de error '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?) , ¿qué me estoy perdiendo?
Eric
1
@Eric: He añadido usingdirectivas que utiliza este fragmento de código.
Beniamin
1
@titol: use HttpClient en lugar de WebClient.
abatishchev
3

Suponiendo que quisiera hacer esto sincrónicamente, usando el método WebClient.OpenRead (...) y estableciendo el tiempo de espera en el Stream que devuelve, obtendrá el resultado deseado:

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 y anular GetWebRequest (...) para establecer el tiempo de espera que sugirió @Beniamin, no funcionó para mí, pero esto sí.

Jeffrymorris
fuente
@jeffymorris no funcionó para mí. Sigo recibiendo WebException diciendo "la solicitud fue abortada - la operación ha expirado" incluso si especifico stream.ReadTimeoutmás grande de lo que realmente tomó para ejecutar la solicitud
chester89
@jeffymoris por otro lado, la solución con la subclase de cliente web tampoco funcionó, por lo que probablemente sea un problema en el lado del servidor
chester89