2008-11-17 6 views
6

Was ist der beste Weg, um es in .NET zu tun? Ich vergesse immer, was ich brauche Dispose() (oder wickeln Sie mit using).C#: Herunterladen einer URL mit Timeout

EDIT: nach einer langen Zeit mit WebRequest, ich habe herausgefunden, über die Anpassung WebClient. Viel besser.

Antwort

6

Nach Thomas Levesque Kommentar here, gibt es eine einfachere und generische Lösung.

Wir erstellen eine WebClient Unterklasse mit Timeout-Unterstützung, und wir bekommen alle WebClient 's Güte.

public class WebClientWithTimeout : WebClient 
{ 
    private readonly int timeoutMilliseconds; 
    public WebClientWithTimeout(int timeoutMilliseconds) 
    { 
    this.timeoutMilliseconds = timeoutMilliseconds; 
    } 

    protected override WebRequest GetWebRequest(Uri address) 
    { 
    var result = base.GetWebRequest(address); 
    result.Timeout = timeoutMilliseconds; 
    return result; 
    } 
} 

Verwendungsbeispiel:

public string GetRequest(Uri uri, int timeoutMilliseconds) 
{ 
    using (var client = new WebClientWithTimeout(timeoutMilliseconds)) 
    { 
    return client.DownloadString(); 
    } 
} 
+1

Scheint nicht mit AsyncDownloadString zu arbeiten: / – ThiefMaster

10

Hier ist, was ich verwende, es scheint zu funktionieren, aber ich weiß nicht, ob es der beste Weg ist:

public string GetRequest(Uri uri, int timeoutMilliseconds) 
{ 
    var request = System.Net.WebRequest.Create(uri); 
    request.Timeout = timeoutMilliseconds; 
    using (var response = request.GetResponse()) 
    using (var stream = response.GetResponseStream()) 
    using (var reader = new System.IO.StreamReader(stream)) 
    { 
     return reader.ReadToEnd(); 
    } 
} 
+0

sieht mir gut .. –

+0

Nicht schlecht für eine einfache URL, die nicht POST-Variable senden erfordert. Sie sollten kennzeichnen, dass Sie Framework 3.5 verwenden ... –

+0

Ich verwende nur asynchrone Anforderungen für Produktionscode. In meiner Antwort finden Sie einen riesigen asynchronen Code, den ich aus MSDN geklont habe und der Zeile myHttpWebRequest.ReadWriteTimeout = DefaultTimeout; –

-5

Run System.Net.WebClient in einem separaten Thread, einen Timer einstellen, es zu töten nach Ihrer maximalen Zeit.

+0

Sie benötigen keinen Thread. Wenn Sie es asynchron tun möchten, können Sie die Methoden BeginGetResponse und EndGetResponse von WebRequest verwenden: http://msdn.microsoft.com/en-us/library/86wf6409.aspx – orip

+0

Jeder Beispielcode darüber? Danke –

11

syncronous Way:

var request = HttpWebRequest.Create("http://www.contoso.com"); 
request.Timeout = 50000; 
using (var response = request.GetResponse()) 
{ 
    //your code here 
} 

Sie können auch die asynchrone Art und Weise haben:

using System; 
using System.Net; 
using System.IO; 
using System.Text; 
using System.Threading; 


public class RequestState 
{ 
    // This class stores the State of the request. 
    const int BUFFER_SIZE = 1024; 
    public StringBuilder requestData; 
    public byte[] BufferRead; 
    public HttpWebRequest request; 
    public HttpWebResponse response; 
    public Stream streamResponse; 
    public RequestState() 
    { 
    BufferRead = new byte[BUFFER_SIZE]; 
    requestData = new StringBuilder(""); 
    request = null; 
    streamResponse = null; 
    } 
} 

class HttpWebRequest_BeginGetResponse 
{ 
    public static ManualResetEvent allDone = new ManualResetEvent(false); 
    const int BUFFER_SIZE = 1024; 
    const int DefaultTimeout = 2 * 60 * 1000; // 2 minutes timeout 

    // Abort the request if the timer fires. 
    private static void TimeoutCallback(object state, bool timedOut) 
    { 
     if (timedOut) 
     { 
      HttpWebRequest request = state as HttpWebRequest; 
      if (request != null) 
      { 
       request.Abort(); 
      } 
     } 
    } 

    static void Main() 
    { 

     try 
     { 
      // Create a HttpWebrequest object to the desired URL. 
      HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.contoso.com"); 
      myHttpWebRequest.ReadWriteTimeout = DefaultTimeout; 


      // Create an instance of the RequestState and assign the previous myHttpWebRequest 
      // object to its request field. 
      RequestState myRequestState = new RequestState(); 
      myRequestState.request = myHttpWebRequest; 


      // Start the asynchronous request. 
      IAsyncResult result = 
       (IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback), myRequestState); 

      // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted 
      ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true); 

      // The response came in the allowed time. The work processing will happen in the 
      // callback function. 
      allDone.WaitOne(); 

      // Release the HttpWebResponse resource. 
      myRequestState.response.Close(); 
     } 
     catch (WebException e) 
     { 
      Console.WriteLine("\nMain Exception raised!"); 
      Console.WriteLine("\nMessage:{0}", e.Message); 
      Console.WriteLine("\nStatus:{0}", e.Status); 
      Console.WriteLine("Press any key to continue.........."); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("\nMain Exception raised!"); 
      Console.WriteLine("Source :{0} ", e.Source); 
      Console.WriteLine("Message :{0} ", e.Message); 
      Console.WriteLine("Press any key to continue.........."); 
      Console.Read(); 
     } 
    } 
    private static void RespCallback(IAsyncResult asynchronousResult) 
    { 
     try 
     { 
      // State of request is asynchronous. 
      RequestState myRequestState = (RequestState)asynchronousResult.AsyncState; 
      HttpWebRequest myHttpWebRequest = myRequestState.request; 
      myRequestState.response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(asynchronousResult); 

      // Read the response into a Stream object. 
      Stream responseStream = myRequestState.response.GetResponseStream(); 
      myRequestState.streamResponse = responseStream; 

      // Begin the Reading of the contents of the HTML page and print it to the console. 
      IAsyncResult asynchronousInputRead = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState); 
      return; 
     } 
     catch (WebException e) 
     { 
      Console.WriteLine("\nRespCallback Exception raised!"); 
      Console.WriteLine("\nMessage:{0}", e.Message); 
      Console.WriteLine("\nStatus:{0}", e.Status); 
     } 
     allDone.Set(); 
    } 
    private static void ReadCallBack(IAsyncResult asyncResult) 
    { 
     try 
     { 

      RequestState myRequestState = (RequestState)asyncResult.AsyncState; 
      Stream responseStream = myRequestState.streamResponse; 
      int read = responseStream.EndRead(asyncResult); 
      // Read the HTML page and then print it to the console. 
      if (read > 0) 
      { 
       myRequestState.requestData.Append(Encoding.ASCII.GetString(myRequestState.BufferRead, 0, read)); 
       IAsyncResult asynchronousResult = responseStream.BeginRead(myRequestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), myRequestState); 
       return; 
      } 
      else 
      { 
       Console.WriteLine("\nThe contents of the Html page are : "); 
       if (myRequestState.requestData.Length > 1) 
       { 
        string stringContent; 
        stringContent = myRequestState.requestData.ToString(); 
        Console.WriteLine(stringContent); 
       } 
       Console.WriteLine("Press any key to continue.........."); 
       Console.ReadLine(); 

       responseStream.Close(); 
      } 

     } 
     catch (WebException e) 
     { 
      Console.WriteLine("\nReadCallBack Exception raised!"); 
      Console.WriteLine("\nMessage:{0}", e.Message); 
      Console.WriteLine("\nStatus:{0}", e.Status); 
     } 
     allDone.Set(); 

    } 
}