2009-11-24 34 views
175

Tôi đang cố gắng tải dữ liệu của máy khách xuống máy cục bộ của mình (theo chương trình) và máy chủ web của chúng rất chậm, gây ra thời gian chờ trong đối tượng WebClient của tôi.Làm thế nào để thay đổi thời gian chờ trên một đối tượng .NET WebClient

Đây là mã của tôi:

WebClient webClient = new WebClient(); 

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

Có cách nào để thiết lập một thời gian chờ vô hạn trên đối tượng này? Hoặc nếu không ai có thể giúp tôi với một ví dụ trên một cách khác để làm điều này?

URL hoạt động tốt trong trình duyệt - chỉ mất khoảng 3 phút để hiển thị.

Trả lời

310

Bạn có thể kéo dài thời gian chờ: kế thừa lớp WebClient gốc và ghi đè trình thu thập dữ liệu web để đặt thời gian chờ của riêng bạn, như trong ví dụ sau. MyWebClient là một lớp học tư nhân trong trường hợp của tôi

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

thời gian chờ mặc định là gì? – knocte

+16

Thời gian chờ mặc định là 100 giây. Mặc dù nó có vẻ chạy trong 30 giây. –

+3

http: // stackoverflow.com/questions/601861/set-timeout-for-webclient-downloadfile – Evgeny

17

Bạn cần sử dụng HttpWebRequest thay vì WebClient vì bạn không thể đặt thời gian chờ trên WebClient mà không kéo dài thời gian chờ (mặc dù nó sử dụng HttpWebRequest). Thay vào đó, sử dụng HttpWebRequest sẽ cho phép bạn đặt thời gian chờ.

+0

Điều này không đúng ... bạn có thể thấy ở trên rằng bạn vẫn có thể sử dụng WebClient, mặc dù thực hiện tùy chỉnh ghi đè WebRequest để đặt thời gian chờ. – DomenicDatti

+7

"System.Net.HttpWebRequest.HttpWebRequest() 'đã lỗi thời:' API này hỗ trợ cơ sở hạ tầng .NET Framework và không được sử dụng trực tiếp từ mã của bạn" – usefulBee

+2

@usefulBee - bởi vì bạn không nên gọi hàm tạo đó: ' "Không sử dụng hàm tạo HttpWebRequest. Sử dụng phương thức WebRequest.Create để khởi tạo các đối tượng HttpWebRequest mới." 'Từ https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest(v=vs.110) .aspx. Ngoài ra, hãy xem http://stackoverflow.com/questions/400565/is-there-any-way-to-inherit-a-class-without-constructors-in-net – ToolmakerSteve

7

Như Sohnee nói, sử dụng System.Net.HttpWebRequest và đặt thuộc tính Timeout thay vì sử dụng System.Net.WebClient.

Tuy nhiên, bạn không thể đặt giá trị thời gian chờ vô hạn (không được hỗ trợ và cố gắng thực hiện như vậy sẽ ném một số ArgumentOutOfRangeException).

tôi khuyên bạn nên đầu tiên thực hiện một yêu cầu HEAD HTTP và kiểm tra giá trị Content-Length tiêu đề trở lại để xác định số byte trong file bạn đang tải và sau đó thiết lập các giá trị thời gian chờ phù hợp cho yêu cầu GET tiếp theo hoặc đơn giản là chỉ định một rất dài giá trị thời gian chờ mà bạn sẽ không bao giờ mong đợi vượt quá.

7

Để hoàn chỉnh, đây là giải pháp kisp của chuyển đến VB (không thể thêm mã để bình luận)

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
'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

Không thể lấy sự w.Timeout mã để làm việc khi rút cáp mạng, nó chỉ là không thời gian ra, chuyển đến sử dụng HttpWebRequest và hiện công việc.

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

Câu trả lời này hoạt động tốt, nhưng đối với bất kỳ ai quan tâm, nếu bạn sử dụng 'var wresp = await request.GetResponseAsync();' thay vì var 'wresp = (HttpWebResponse) request.GetResponse();' bạn sẽ nhận được một timeout lớn một lần nữa – andrewjboyd

8

Giải pháp đầu tiên không có tác dụng đối với tôi nhưng đây là một số mã đã hoạt động đối với tôi.

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); 
     } 
    } 
Các vấn đề liên quan