Ustaw limit czasu dla webClient.DownloadFile ()

92

Używam webClient.DownloadFile()do pobrania pliku. Czy mogę ustawić limit czasu, aby to nie potrwać tak długo, jeśli nie może uzyskać dostępu do pliku?

UnkwnTech
źródło

Odpowiedzi:

42

Spróbuj WebClient.DownloadFileAsync(). Możesz zadzwonić CancelAsync()według timera z własnym limitem czasu.

abatishchev
źródło
2
Nie chcę używać minutnika ani stopera. Chcę mieć wbudowane podejście do hacka lub interfejsu API. Używanie timera / stopera kosztuje mnie dodatkowy wątek do oglądania, podczas gdy ta funkcja może już zaimplementowana, więc po co wymyślać koło na
@Kilanny: następnie przejdź do rozwiązania z innej odpowiedzi. Lub użyj HttpClient i ustaw właściwość Timeout. Proszę również zwrócić uwagę, że ta odpowiedź pochodzi z 2009 roku.
abatishchev
8
w .Net 4.5+ możesz również użyć, var taskDownload = client.DownloadFileTaskAsync(new Uri("http://localhost/folder"),"filename")a potemtaskDownload.Wait(TimeSpan.FromSeconds(5));
itsho
257

Moja odpowiedź pochodzi stąd

Możesz utworzyć klasę pochodną, ​​która ustawi właściwość timeout WebRequestklasy bazowej :

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

i można go używać tak samo, jak podstawowej klasy WebClient.

Beniamin
źródło
3
Nie rozczarować ktoś natknie tym pomocne kodu musiałem ustawić czas oczekiwania przed wywołaniem base.GetWebRequest (adres)
Darthtong
Resharper narzeka na możliwą wartość null dla „result” i sugeruje sprawdzenie wartości null przed ustawieniem wartości Timeout na WebRequest. Patrząc na zdekompilowany kod, wydaje się to niemożliwe, chyba że podasz niestandardowy moduł WebRequestModules w swoim pliku web.config, ale dla takiej pozytywnej odpowiedzi dodałbym go na wszelki wypadek.
Kevin Coulombe
W tej linii pojawia się błąd request.Timeout. Błąd msg '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?) , czego mi brakuje?
Eric,
1
@Eric: Dodałem usingdyrektywy używane przez ten fragment kodu.
Beniamin
1
@titol: użyj HttpClient zamiast WebClient.
abatishchev
3

Zakładając, że chciałeś to zrobić synchronicznie, używając metody WebClient.OpenRead (...) i ustawienie limitu czasu w zwracanym strumieniu da pożądany wynik:

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

Wyprowadzenie z WebClient i przesłanianie GetWebRequest (...) w celu ustawienia limitu czasu zasugerowanego przez @Beniamin nie działało dla mnie jako, ale tak się stało.

jeffrymorris
źródło
@jeffymorris nie działa dla mnie. Wciąż otrzymuję WebException z komunikatem „żądanie zostało przerwane - upłynął limit czasu operacji”, nawet jeśli stream.ReadTimeout
określę wartość
@jeffymoris z drugiej strony, rozwiązanie z podklasą webclient też nie działało, więc prawdopodobnie problem po stronie serwera
chester89