Come modificare il timeout su un object WebClient .NET

Sto cercando di scaricare i dati di un cliente sul mio computer locale (programmaticamente) e il loro server web è molto, molto lento e causa un timeout nel mio object WebClient .

Ecco il mio codice:

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

C’è un modo per impostare un timeout infinito su questo object? O se no qualcuno può aiutarmi con un esempio su un modo alternativo per fare questo?

L’URL funziona bene in un browser: bastano circa 3 minuti per essere visualizzati.

È ansible estendere il timeout: ereditare la class WebClient originale ed eseguire l’override del getter di richiesta Web per impostare il proprio timeout, come nell’esempio seguente. MyWebClient era una class privata nel mio caso

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

È necessario utilizzare HttpWebRequest anziché WebClient poiché non è ansible impostare il timeout su WebClient senza estenderlo (anche se utilizza HttpWebRequest ). Usando HttpWebRequest invece ti permetterà di impostare il timeout.

La prima soluzione non ha funzionato per me, ma qui c’è un codice che ha funzionato per me.

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

Imansible ottenere il w.Timeout codice per funzionare quando tirato fuori il cavo di rete, semplicemente non è scaduto, spostato a utilizzare HttpWebRequest e fa il lavoro ora.

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

Come dice Sohnee, usando System.Net.HttpWebRequest e imposta la proprietà Timeout invece di usare System.Net.WebClient .

Non è tuttavia ansible impostare un valore di timeout infinito (non è supportato e il tentativo di farlo genererà ArgumentOutOfRangeException ).

Ti consigliamo di eseguire prima una richiesta HEAD HTTP e di esaminare il valore dell’intestazione Content-Length restituito per determinare il numero di byte nel file che stai scaricando e quindi impostare il valore di timeout di conseguenza per la successiva richiesta GET o semplicemente specificando un timeout molto lungo valore che non ti aspetteresti mai di superare.

 '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 

Per completezza, ecco la soluzione di Kisp trasferita su VB (non è ansible aggiungere codice a un commento)

 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