尝试... Catch和HTTP请求

时间:2010-01-29 12:43:38

标签: c#

我的程序发出了Web请求,但有时我会得到一个异常,说服务器关闭了连接。发生这种情况时,我需要重新打开一个连接。

我应该把代码放在try ... catch吗?如果在try中关闭连接,请在catch中重新打开它?但我的问题是,如果服务器关闭了在catch中打开的连接怎么办?

这是我目前的代码。

public String postRequest(String pD, String url)
    {
        String postData = pD;

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        byte[] buffer = Encoding.ASCII.GetBytes(postData);

        /** Set the headers **/
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = buffer.Length;
        request.ServicePoint.Expect100Continue = false;
        request.Method = "post";

        Stream PostData = request.GetRequestStream();
        PostData.Write(buffer, 0, buffer.Length);
        PostData.Close();

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        Stream responseStream = response.GetResponseStream();
        StreamReader read = new StreamReader(responseStream);

        String line; String source = "";
        while ((line = read.ReadLine()) != null) source += line;
        return source;
     }

3 个答案:

答案 0 :(得分:2)

试试Execute-Around method。 该对象采用委托,将委托作为代码块/委托完成。 object.Execute

  • 有一个预阻塞,可以检查conn是否仍然打开。如果不是,请重试x次,直到建立连接
  • 致电代表
  • 清理(如果你认为合适,可以打开conn)

更新:好的。 (我昨天赶紧回答)。我之前的回答假设有一种方法可以知道连接是否仍处于活动/打开状态。但是,如果我的问题推理能力是正确的,那么问题就是你不能确定conn是否存活,除非你实际使用它并接收异常。

我想了一会儿,也许我正受到我正在阅读的这本书的影响...... 我认为你需要的是相当于ruby rescue-n-retry方法

begin
   # do stuff for sending a request
rescue ConnectionClosedError
   # handle the error to ensure that a retry has a chance of succeeding
   retry 
end

现在我不认为你在C#中本地拥有它,但是可以编写足够接近的等效脚本。用goto(屏蔽!)。这是goto简单清洁的罕见情况之一。一个例子是

static void Main()
{
    for (int i = 0; i < 10; i++)
    {
        PostRequest();
    }
}
private static void PostRequest()
{
    Console.Write("Start...");

Retry:
    try
    {
        CodeThatMightThrowAnException();
        Console.WriteLine("Done!");
    }
    catch (ConnectionClosedException e)
    {
        Console.Write("Error! Attempt to reconnect...");
        goto Retry;
    }
}

static Random _randomizer = new Random();
private static void CodeThatMightThrowAnException()
{   var randomEvent = _randomizer.Next(20);
    Console.Write("- {0} -", randomEvent);
    if ( randomEvent % 3 == 0)
        throw new ConnectionClosedException("Server dropped me!");
}

输出:

Start...- 10 -Done!
Start...- 16 -Done!
Start...- 9 -Error! Attempt to reconnect...- 14 -Done!
Start...- 0 -Error! Attempt to reconnect...- 3 -Error! Attempt to reconnect...-
19 -Done!
Start...- 15 -Error! Attempt to reconnect...- 6 -Error! Attempt to reconnect...-
 5 -Done!
Start...- 2 -Done!
Start...- 14 -Done!
Start...- 13 -Done!
Start...- 14 -Done!
Start...- 19 -Done!

注意:当然,您需要跟踪所需的状态,并防止进入无限重试循环。

答案 1 :(得分:2)

我会循环直到达到指定的重试限制:

for(int retryCount = 0; retryCount < 5; retryCount++) {
    try {
        String postData = pD;
        ...
        return source;
    } catch(Exception e) {
        // perhaps log exception?
    }
}

正如nos已经指出的那样,你必须确保你的资源正确发布。

答案 2 :(得分:1)

postRequest的调用者执行try / catch并确定是否应该重试。

在postRequest内部,确保即使发生异常,也要正确清理,例如你的Streams应该包含在using()子句中。