My program makes web requests, but sometimes I will get an exception saying the server closed the connection. When this happens I need to re-open a connection.
Should I put the code in a try ... catch? If the connection is closed in the try, reope开发者_开发百科n it in the catch? But my issue would be, what if the servers closes the connection opened in the catch?
Here is my code at the moment.
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;
}
I would simply loop until I reach a specified retry-limit:
for(int retryCount = 0; retryCount < 5; retryCount++) {
try {
String postData = pD;
...
return source;
} catch(Exception e) {
// perhaps log exception?
}
}
As nos already pointed out, you have to make sure that your resources are released properly.
Try Execute-Around method. This object takes a delegate that takes the work to be done as a code-block/delegate. object.Execute would
- have a pre-block which would check if the conn is still open. If not, retry x times till a connection is established
- call the delegate
- clean up (leave the conn open if you deem fit)
Update: Ok. (I answered in a hurry yesterday). My previous answer assumed that there is a way to know if the connection is still alive/open. But if my problem-inference powers are right, the issue is that you can't be sure that the conn is alive unless you actually use it and receive an exception.
I thought about it for a while and maybe I am being influenced by the book I am reading right now... I think what you need is the equivalent of a ruby rescue-n-retry approach
begin
# do stuff for sending a request
rescue ConnectionClosedError
# handle the error to ensure that a retry has a chance of succeeding
retry
end
Now I don't think you have this natively in C#, however can script a close-enough equiv. with a goto
(shields up!). This is one of the rare cases where goto is simpler-n-clean. An example would be
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!");
}
Output:
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!
Note: Of course you need to keep track of required state and also safeguard against going into an infinite retry loop.
Have the caller of postRequest
do the try /catch and decide if it should retry.
inside postRequest, make sure your're cleaning up properly even if an exception is thrown e.g. your Streams should be wrapped in a using() clause.
精彩评论