代码之家  ›  专栏  ›  技术社区  ›  Ryall

如何更改.NET WebClient对象的超时

  •  202
  • Ryall  · 技术社区  · 16 年前

    我正在尝试将客户机的数据下载到我的本地计算机(以编程方式),他们的Web服务器速度非常非常慢,这导致我的 WebClient 对象。

    这是我的代码:

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

    有没有办法在这个对象上设置无限超时?或者如果没有,有人能帮我举一个例子来做这个吗?

    该URL在浏览器中工作正常-仅需3分钟即可显示。

    8 回复  |  直到 7 年前
        1
  •  346
  •   Uwe Keim    7 年前

    您可以扩展超时:继承原始的WebClient类并重写WebRequest getter以设置自己的超时,如下例所示。

    在我的例子中,MyWebClient是一个私有类:

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

    你需要使用 HttpWebRequest 而不是 WebClient 因为你不能设置超时 网络客户端 不扩展它(即使它使用 HTTPWebRebug )使用 HTTPWebRebug 而是允许您设置超时。

        3
  •  16
  •   Davinci Jeremie    11 年前

    第一个解决方案不适用于我,但这里有一些代码确实适用于我。

        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);
            }
        }
    
        4
  •  10
  •   themullet    11 年前

    当拔出网线时,无法使w.timeout代码工作,它只是没有超时,移动到使用httpwebrequest并立即执行该任务。

    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);
    }
    
        5
  •  8
  •   GlennG    13 年前

    为了完整性,这里是kisp的解决方案移植到vb(不能在注释中添加代码)

    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
    
        6
  •  7
  •   dariom    16 年前

    如Sohnee所说,使用 System.Net.HttpWebRequest 并设置 Timeout 属性而不是使用 System.Net.WebClient .

    但是,您不能设置无限超时值(不支持该值,尝试这样做会引发 ArgumentOutOfRangeException )

    我建议先表演 HEAD HTTP 请求并检查 Content-Length 返回的头值确定要下载的文件中的字节数,然后相应地为后续文件设置超时值 GET 请求或只是指定一个非常长的超时值,您永远不会期望超过这个值。

        7
  •  7
  •   Josh    13 年前
    '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
  •  0
  •   Konstantin S.    7 年前

    用途:

    using (var client = new TimeoutWebClient(TimeSpan.FromSeconds(10)))
    {
        return await client.DownloadStringTaskAsync(url);
    }
    

    班级:

    using System;
    using System.Net;
    
    namespace Utilities
    {
        public class TimeoutWebClient : WebClient
        {
            public TimeSpan Timeout { get; set; }
    
            public TimeoutWebClient(TimeSpan timeout)
            {
                Timeout = timeout;
            }
    
            protected override WebRequest GetWebRequest(Uri uri)
            {
                var request = base.GetWebRequest(uri);
                if (request == null)
                {
                    return null;
                }
    
                var timeoutInMillisecond = (int) Timeout.TotalMilliseconds;
    
                request.Timeout = timeoutInMillisecond;
                if (request is HttpWebRequest httpWebRequest)
                {
                    httpWebRequest.ReadWriteTimeout = timeoutInMillisecond;
                }
    
                return request;
            }
        }
    }
    
    推荐文章