Cómo cambiar el tiempo de espera en un objeto WebClient .NET

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 .

Aquí está mi código:

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

¿Hay alguna forma 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.

Puede extender 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 siguiente ejemplo. 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; } } 

Necesita utilizar HttpWebRequest lugar de WebClient ya que no puede establecer el tiempo de espera en WebClient sin ampliarlo (aunque utilice HttpWebRequest ). El uso de HttpWebRequest en HttpWebRequest lugar le permitirá establecer el tiempo de espera.

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

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

No se pudo conseguir que el código w.Timeout funcione cuando se desconectó el cable de red, simplemente no se agotó el tiempo de espera, se movió a usar HttpWebRequest y ahora funciona.

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

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

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

Recomiendo primero realizar una solicitud HTTP HEAD y examinar el valor del encabezado Content-Length devuelto para determinar el número de bytes en el archivo que está descargando y luego establecer el valor de tiempo de espera para la siguiente solicitud GET o simplemente especificando un tiempo de espera muy largo valor que nunca esperarías exceder.

 '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 

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

 Namespace Utils '''  ''' Subclass of WebClient to provide access to the timeout property '''  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 '''  ''' Set the web call timeout in Milliseconds '''  '''  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