How to change the timeout on a .NET WebClient obje

2019-01-01 06:42发布

I am trying to download a client's data to my local machine (programatically) and their webserver is very, very slow which is causing a timeout in my WebClient object.

Here is my code:

WebClient webClient = new WebClient();

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

Is there a way to set an infinite timeout on this object? Or if not can anyone help me with an example on an alternate way to do this?

The URL works fine in a browser - it just takes about 3 minutes to show.

7条回答
裙下三千臣
2楼-- · 2019-01-01 07:22

As Sohnee says, using System.Net.HttpWebRequest and set the Timeout property instead of using System.Net.WebClient.

You can't however set an infinite timeout value (it's not supported and attempting to do so will throw an ArgumentOutOfRangeException).

I'd recommend first performing a HEAD HTTP request and examining the Content-Length header value returned to determine the number of bytes in the file you're downloading and then setting the timeout value accordingly for subsequent GET request or simply specifying a very long timeout value that you would never expect to exceed.

查看更多
余生无你
3楼-- · 2019-01-01 07:25

Couldn't get the w.Timeout code to work when pulled out the network cable, it just wasn't timing out, moved to using HttpWebRequest and does the job now.

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);
}
查看更多
牵手、夕阳
4楼-- · 2019-01-01 07:37
'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
查看更多
余生请多指教
5楼-- · 2019-01-01 07:43

You can extend the timeout: inherit the original WebClient class and override the webrequest getter to set your own timeout, like in the following example. MyWebClient was a private class in my case

  private class MyWebClient : WebClient
    {
        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest w = base.GetWebRequest(uri);
            w.Timeout = 20 * 60 * 1000;
            return w;
        }
    }
查看更多
看风景的人
6楼-- · 2019-01-01 07:43

For completeness, here's kisp's solution ported to VB (can't add code to a comment)

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楼-- · 2019-01-01 07:44

The first solution did not work for me but here is some code that did work for 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);
        }
    }
查看更多
登录 后发表回答