Como alterar o tempo limite em um object .NET WebClient

Eu estou tentando baixar os dados de um cliente para minha máquina local (programaticamente) e seu servidor web é muito, muito lento que está causando um tempo limite no meu object WebClient .

Aqui está o meu código:

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

Existe uma maneira de definir um tempo limite infinito neste object? Ou, se não, alguém pode me ajudar com um exemplo de uma maneira alternativa de fazer isso?

O URL funciona bem em um navegador – leva apenas cerca de 3 minutos para ser exibido.

Você pode estender o tempo limite: herda a class WebClient original e sobrescreve o getter de solicitação da Web para definir seu próprio tempo limite, como no exemplo a seguir. MyWebClient era uma class privada no meu caso

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

Você precisa usar HttpWebRequest vez de WebClient pois não é possível definir o tempo limite no WebClient sem estendê-lo (mesmo que ele use o HttpWebRequest ). Usando o HttpWebRequest vez disso, permitirá que você defina o tempo limite.

A primeira solução não funcionou para mim, mas aqui está um código que funcionou para mim.

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

Não foi possível obter o código w.Timeout para trabalhar quando puxou o cabo de rede, ele simplesmente não foi o tempo limite, passou a usar o HttpWebRequest e faz o trabalho agora.

 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 diz Sohnee, usando System.Net.HttpWebRequest e defina a propriedade Timeout em vez de usar System.Net.WebClient .

Você não pode, no entanto, definir um valor de tempo limite infinito (não é suportado e, ao tentar fazer isso, lançará um ArgumentOutOfRangeException ).

Eu recomendaria primeiro executar uma solicitação HEAD HTTP e examinar o valor do header Content-Length retornado para determinar o número de bytes no arquivo que você está baixando e, em seguida, definir o valor de tempo limite de acordo com a solicitação GET subsequente ou simplesmente especificar um tempo limite muito longo valor que você nunca esperaria 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, aqui está a solução do kisp para o VB (não é possível adicionar código a um comentário)

 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