Imposta timeout per webClient.DownloadFile ()


92

Sto usando webClient.DownloadFile()per scaricare un file, posso impostare un timeout per questo in modo che non impieghi così tanto tempo se non può accedere al file?

Risposte:


42

Prova WebClient.DownloadFileAsync(). Puoi chiamare CancelAsync()tramite timer con il tuo timeout.


2
Non voglio usare il timer o il cronometro. Voglio un hack o un approccio api integrato. L'uso del timer / cronometro mi costa thread aggiuntivi per la visione, mentre questa funzione potrebbe essere già implementata, quindi perché reinventare la ruota

@Kilanny: quindi vai con la soluzione da un'altra risposta. Oppure usa HttpClient e imposta la proprietà Timeout. Inoltre, tieni presente che questa risposta è del 2009.
abatishchev

8
in .Net 4.5+ puoi anche usare var taskDownload = client.DownloadFileTaskAsync(new Uri("http://localhost/folder"),"filename")e poitaskDownload.Wait(TimeSpan.FromSeconds(5));
itsho

257

La mia risposta viene da qui

Puoi creare una classe derivata, che imposterà la proprietà timeout della 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 puoi usarlo proprio come la classe WebClient di base.


3
Solo nel caso in cui qualcun altro si imbattesse in questo codice utile, ho dovuto impostare il timeout prima di chiamare la base.GetWebRequest (indirizzo)
Darthtong

Resharper si lamenta di un possibile valore nullo per "risultato" e suggerisce un controllo nullo prima di impostare il valore di Timeout su WebRequest. Guardando il codice decompilato, sembra impossibile a meno che tu non fornisca un WebRequestModules personalizzato nel tuo web.config, ma per una risposta così votata, la aggiungerei per ogni evenienza.
Kevin Coulombe

Ricevo l'errore su questa riga request.Timeout. Messaggio di errore '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?) , cosa mi manca?
Eric

1
@ Eric: ho aggiunto using direttive utilizzate da questo frammento di codice.
Beniamin

1
@titol: usa HttpClient piuttosto che WebClient.
abatishchev

3

Supponendo che tu voglia farlo in modo sincrono, utilizzando il metodo WebClient.OpenRead (...) e impostando il timeout sullo Stream che restituisce, otterrai il risultato desiderato:

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

Derivare da WebClient e sovrascrivere GetWebRequest (...) per impostare il timeout suggerito da @Beniamin, non ha funzionato per me, ma ha funzionato.


@jeffymorris non ha funzionato per me. Continuo a ricevere WebException che dice "la richiesta è stata interrotta - l'operazione è scaduta" anche se stream.ReadTimeout
indico un valore

@ jeffymoris dall'altro, la soluzione con la sottoclasse webclient non ha funzionato, quindi probabilmente è un problema sul lato server
chester89
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.