Définir le délai d'expiration pour webClient.DownloadFile ()

92

J'utilise webClient.DownloadFile()pour télécharger un fichier puis-je définir un délai pour cela afin que cela ne prenne pas si longtemps s'il ne peut pas accéder au fichier?

UnkwnTech
la source

Réponses:

42

Essayez WebClient.DownloadFileAsync(). Vous pouvez appeler CancelAsync()par minuterie avec votre propre délai.

abatishchev
la source
2
Je ne veux pas utiliser de minuterie ou de chronomètre. Je veux une approche intégrée de hack ou api. L'utilisation de la minuterie / chronomètre me coûte un fil supplémentaire pour regarder, alors que cette fonctionnalité est peut-être déjà implémentée, alors pourquoi réinventer la roue
@Kilanny: alors optez pour la solution d'une autre réponse. Ou utilisez HttpClient et définissez la propriété Timeout. Veuillez également noter que cette réponse date de 2009.
abatishchev
8
dans .Net 4.5+, vous pouvez également utiliser var taskDownload = client.DownloadFileTaskAsync(new Uri("http://localhost/folder"),"filename")et puistaskDownload.Wait(TimeSpan.FromSeconds(5));
itsho
257

Ma réponse vient d' ici

Vous pouvez créer une classe dérivée, qui définira la propriété timeout de la WebRequestclasse de 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;
    }
}

et vous pouvez l'utiliser comme la classe WebClient de base.

Beniamin
la source
3
Juste au cas où quelqu'un d'autre trouverait ce code utile, j'ai dû définir le délai avant d'appeler base.GetWebRequest (adresse)
Darthtong
Resharper se plaint d'une éventuelle valeur nulle pour "result" et suggère une vérification nulle avant de définir la valeur Timeout sur WebRequest. En regardant le code décompilé, cela semble impossible à moins que vous ne fournissiez un WebRequestModules personnalisé dans votre web.config, mais pour une telle réponse, je l'ajouterais au cas où.
Kevin Coulombe
J'obtiens l'erreur sur cette ligne request.Timeout. Message d'erreur '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?) , que me manque-t-il?
Eric
1
@Eric: J'ai ajouté des usingdirectives qui sont utilisées par cet extrait de code.
Beniamin
1
@titol: utilisez HttpClient plutôt que WebClient.
abatishchev
3

En supposant que vous vouliez le faire de manière synchrone, utiliser la méthode WebClient.OpenRead (...) et définir le délai d'expiration sur le Stream qu'il renvoie vous donnera le résultat souhaité:

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

Dériver de WebClient et remplacer GetWebRequest (...) pour définir le délai d'expiration suggéré par @Beniamin n'a pas fonctionné pour moi, mais cela a fonctionné.

Jeffrymorris
la source
@jeffymorris n'a pas fonctionné pour moi. Je reçois toujours WebException disant "la demande a été abandonnée - l'opération a expiré" même si je spécifie stream.ReadTimeoutplus grand que ce qu'il a réellement fallu pour exécuter la demande
chester89
@jeffymoris d'autre part, la solution avec la sous-classe webclient ne fonctionnait pas non plus, donc c'est probablement un problème côté serveur
chester89