web-dev-qa-db-fra.com

Comment modifier le délai d'attente sur un objet .NET WebClient

J'essaie de télécharger (par programme) les données d'un client sur mon ordinateur local et leur serveur Web est très, très lent, ce qui provoque un dépassement du délai d'attente de mon objet WebClient.

Voici mon code:

WebClient webClient = new WebClient();

webClient.Encoding = Encoding.UTF8;
webClient.DownloadFile(downloadUrl, downloadFile);

Est-il possible de définir un délai d'expiration infini sur cet objet? Ou sinon, est-ce que quelqu'un peut m'aider avec un exemple sur un autre moyen de le faire?

L'URL fonctionne bien dans un navigateur - l'affichage ne prend que 3 minutes environ.

212
Ryall

Vous pouvez prolonger le délai d'attente: hériter de la classe WebClient d'origine et remplacer le getter webrequest pour définir votre propre délai d'attente, comme dans l'exemple suivant.

MyWebClient était un cours privé dans mon cas:

private class MyWebClient : WebClient
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
        WebRequest w = base.GetWebRequest(uri);
        w.Timeout = 20 * 60 * 1000;
        return w;
    }
}
360
kisp

La première solution n'a pas fonctionné pour moi, mais voici un code qui a fonctionné pour moi.

    private class WebClient : System.Net.WebClient
    {
        public int Timeout { get; set; }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest lWebRequest = base.GetWebRequest(uri);
            lWebRequest.Timeout = Timeout;
            ((HttpWebRequest)lWebRequest).ReadWriteTimeout = Timeout;
            return lWebRequest;
        }
    }

    private string GetRequest(string aURL)
    {
        using (var lWebClient = new WebClient())
        {
            lWebClient.Timeout = 600 * 60 * 1000;
            return lWebClient.DownloadString(aURL);
        }
    }
22
Davinci Jeremie

Vous devez utiliser HttpWebRequest plutôt que WebClient car vous ne pouvez pas définir le délai d’attente sur WebClient sans le prolonger (même s’il utilise HttpWebRequest). L'utilisation de HttpWebRequest vous permettra de définir le délai.

20
Fenton

Impossible de faire fonctionner le code w.Timeout lorsque le câble réseau est débranché, il n’a pas dépassé le délai imparti, il est passé à l’utilisation de HttpWebRequest et effectue le travail à présent.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(downloadUrl);
request.Timeout = 10000;
request.ReadWriteTimeout = 10000;
var wresp = (HttpWebResponse)request.GetResponse();

using (Stream file = File.OpenWrite(downloadFile))
{
    wresp.GetResponseStream().CopyTo(file);
}
10
themullet

Pour être complet, voici la solution de kisp portée sur VB (impossible d'ajouter du code à un commentaire)

Namespace Utils

''' <summary>
''' Subclass of WebClient to provide access to the timeout property
''' </summary>
Public Class WebClient
    Inherits System.Net.WebClient

    Private _TimeoutMS As Integer = 0

    Public Sub New()
        MyBase.New()
    End Sub
    Public Sub New(ByVal TimeoutMS As Integer)
        MyBase.New()
        _TimeoutMS = TimeoutMS
    End Sub
    ''' <summary>
    ''' Set the web call timeout in Milliseconds
    ''' </summary>
    ''' <value></value>
    Public WriteOnly Property setTimeout() As Integer
        Set(ByVal value As Integer)
            _TimeoutMS = value
        End Set
    End Property


    Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest
        Dim w As System.Net.WebRequest = MyBase.GetWebRequest(address)
        If _TimeoutMS <> 0 Then
            w.Timeout = _TimeoutMS
        End If
        Return w
    End Function

End Class

End Namespace
8
GlennG
'CORRECTED VERSION OF LAST FUNCTION IN VISUAL BASIC BY GLENNG

Protected Overrides Function GetWebRequest(ByVal address As System.Uri) As System.Net.WebRequest
            Dim w As System.Net.WebRequest = MyBase.GetWebRequest(address)
            If _TimeoutMS <> 0 Then
                w.Timeout = _TimeoutMS
            End If
            Return w  '<<< NOTICE: MyBase.GetWebRequest(address) DOES NOT WORK >>>
        End Function
7
Josh

Comme le dit Sohnee, utilisez System.Net.HttpWebRequest et définissez la propriété Timeout au lieu d’utiliser _System.Net.WebClient_.

Vous ne pouvez toutefois pas définir une valeur de délai d'expiration infini (cette option n'est pas prise en charge et toute tentative de le faire générera un ArgumentOutOfRangeException).

Je recommanderais d'abord d'effectuer une requête HEAD HTTP et d'examiner la valeur d'en-tête _Content-Length_ renvoyée pour déterminer le nombre d'octets dans le fichier que vous téléchargez, puis de définir la valeur de délai en conséquence, GET demande ou spécifiez simplement une valeur de délai d'attente très longue que vous ne vous attendez jamais à dépasser.

7
dariom

Usage:

using (var client = new TimeoutWebClient(TimeSpan.FromSeconds(10)))
{
    return await client.DownloadStringTaskAsync(url);
}

Classe:

using System;
using System.Net;

namespace Utilities
{
    public class TimeoutWebClient : WebClient
    {
        public TimeSpan Timeout { get; set; }

        public TimeoutWebClient(TimeSpan timeout)
        {
            Timeout = timeout;
        }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            var request = base.GetWebRequest(uri);
            if (request == null)
            {
                return null;
            }

            var timeoutInMilliseconds = (int) Timeout.TotalMilliseconds;

            request.Timeout = timeoutInMilliseconds;
            if (request is HttpWebRequest httpWebRequest)
            {
                httpWebRequest.ReadWriteTimeout = timeoutInMilliseconds;
            }

            return request;
        }
    }
}
2
Konstantin S.