2009-11-24 42 views
175

Estoy tratando de descargar los datos de un cliente a mi máquina local (programáticamente) y su servidor web es muy, muy lento, lo que está causando un tiempo de espera en mi objeto WebClient.Cómo cambiar el tiempo de espera en un objeto WebClient .NET

Aquí está mi código:

WebClient webClient = new WebClient(); 

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

¿Hay una manera de establecer un tiempo de espera infinito en este objeto? O si no, ¿alguien puede ayudarme con un ejemplo de una manera alternativa de hacer esto?

La URL funciona bien en un navegador; solo demora unos 3 minutos en mostrarse.

Respuesta

310

Puede prolongar el tiempo de espera: herede la clase WebClient original y anule el getter de webrequest para establecer su propio tiempo de espera, como en el ejemplo siguiente. MyWebClient era una clase privada en mi caso

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

¿Cuál es el tiempo de espera predeterminado? – knocte

+16

El tiempo de espera predeterminado es de 100 segundos. Aunque parece funcionar durante 30 segundos. –

+3

http: // stackoverflow.com/questions/601861/set-timeout-for-webclient-downloadfile – Evgeny

17

Debe usar HttpWebRequest en lugar de WebClient ya que no puede establecer el tiempo de espera en WebClient sin extenderlo (aunque usa HttpWebRequest). Usar el HttpWebRequest en su lugar le permitirá establecer el tiempo de espera.

+0

Esto no es cierto ... puede ver anteriormente que todavía puede usar WebClient, aunque una implementación personalizada que anula WebRequest para establecer el tiempo de espera. – DomenicDatti

+7

"System.Net.HttpWebRequest.HttpWebRequest() 'está obsoleto:' Esta API admite la infraestructura de .NET Framework y no está destinada a ser utilizada directamente desde su código" – usefulBee

+2

@usefulBee - porque no debe llamar a ese constructor: ' "No use el constructor HttpWebRequest. Use el método WebRequest.Create para inicializar nuevos objetos HttpWebRequest." 'Desde https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest(v=vs.110) .aspx. También vea http://stackoverflow.com/questions/400565/is-there-any-way-to-inherit-a-class-without-constructors-in-net – ToolmakerSteve

7

Como dice Sohnee, usando System.Net.HttpWebRequest y configurando la propiedad Timeout en lugar de usar System.Net.WebClient.

No obstante, no puede establecer un valor de tiempo de espera infinito (no es compatible e intentar hacerlo arrojará un ArgumentOutOfRangeException).

Me gustaría recomendar realizar primero una solicitud HEAD HTTP y examinando el valor Content-Length cabecera volvió a determinar el número de bytes en el archivo que está descargando y luego establecer el valor de tiempo de espera en consecuencia para la posterior solicitud GET o simplemente especificando un tiempo muy largo valor de tiempo de espera que nunca esperaría exceder.

7

Para completar, aquí está la solución de kisp portado a VB (no se puede agregar código a un comentario)

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 
7
'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 
8

No se pudo obtener la w.Código de tiempo para trabajar cuando se sacó el cable de red, simplemente no estaba agotado el tiempo, se movió a usar HttpWebRequest y hace el trabajo ahora.

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

Esta respuesta funciona muy bien, pero para cualquier persona interesado, si usa 'var wresp = aguarde request.GetResponseAsync();' en lugar de var 'wresp = (HttpWebResponse) request.GetResponse();' obtendrá un tiempo de espera masivo de nuevo – andrewjboyd

8

La primera solución no funcionó, pero aquí hay un código que me funcionó.

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