所以我的应用程序正在与服务器交换请求/响应(没有问题),直到互联网连接死了几秒钟,然后又回来了。然后像这样的代码:
response = (HttpWebResponse)request.GetResponse();
会抛出异常,状态为ReceiveFailure
,ConnectFailure
,KeepAliveFailure
等。
现在,非常重要的是,如果互联网连接回来,我可以继续与服务器通信,否则我必须从头开始,这需要很长时间。
当互联网回来时,您将如何恢复此通信?
此刻,我一直在检查是否有可能与服务器通信,直到可能(至少在理论上)。我的代码尝试看起来像这样:
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
// We have a problem receiving stuff from the server.
// We'll keep on trying for a while
if (ex.Status == WebExceptionStatus.ReceiveFailure ||
ex.Status == WebExceptionStatus.ConnectFailure ||
ex.Status == WebExceptionStatus.KeepAliveFailure)
{
bool stillNoInternet = true;
// keep trying to talk to the server
while (stillNoInternet)
{
try
{
response = (HttpWebResponse)request.GetResponse();
stillNoInternet = false;
}
catch
{
stillNoInternet = true;
}
}
}
}
然而,问题是即使互联网回来,第二个try-catch语句仍然会抛出异常。
我做错了什么?还有另一种方法可以解决这个问题吗?
谢谢!
答案 0 :(得分:17)
您应该每次都重新创建请求,并且应该在循环中执行重试,并在每次重试之间等待。等待时间应该随着每次失败而逐渐增加。
E.g。
ExecuteWithRetry (delegate {
// retry the whole connection attempt each time
HttpWebRequest request = ...;
response = request.GetResponse();
...
});
private void ExecuteWithRetry (Action action) {
// Use a maximum count, we don't want to loop forever
// Alternativly, you could use a time based limit (eg, try for up to 30 minutes)
const int maxRetries = 5;
bool done = false;
int attempts = 0;
while (!done) {
attempts++;
try {
action ();
done = true;
} catch (WebException ex) {
if (!IsRetryable (ex)) {
throw;
}
if (attempts >= maxRetries) {
throw;
}
// Back-off and retry a bit later, don't just repeatedly hammer the connection
Thread.Sleep (SleepTime (attempts));
}
}
}
private int SleepTime (int retryCount) {
// I just made these times up, chose correct values depending on your needs.
// Progressivly increase the wait time as the number of attempts increase.
switch (retryCount) {
case 0: return 0;
case 1: return 1000;
case 2: return 5000;
case 3: return 10000;
default: return 30000;
}
}
private bool IsRetryable (WebException ex) {
return
ex.Status == WebExceptionStatus.ReceiveFailure ||
ex.Status == WebExceptionStatus.ConnectFailure ||
ex.Status == WebExceptionStatus.KeepAliveFailure;
}
答案 1 :(得分:1)
我认为你要做的是:
HttpWebResponse RetryGetResponse(HttpWebRequest request)
{
while (true)
{
try
{
return (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
if (ex.Status != WebExceptionStatus.ReceiveFailure &&
ex.Status != WebExceptionStatus.ConnectFailure &&
ex.Status != WebExceptionStatus.KeepAliveFailure)
{
throw;
}
}
}
}
如果你想在失败时重试一些东西,那么不要把它想象成你想要做的事情,而是把它想象成循环,直到你成功为止。 (或者您不想重试的失败)。上面的内容将继续重试,直到返回响应或抛出不同的异常为止。
引入某种最大重试限制也是一个好主意(例如,在1小时后停止重试)。
答案 2 :(得分:0)
如果当你恢复连接时它仍在执行 - 那么我的猜测是它只是再次返回相同的结果。
您可能希望每次尝试重新创建请求,除此之外我没有看到代码或逻辑有多大错误。除了你永远阻止这个线程的事实。但是,如果这本身就是一个工作线程,那可能就没问题了。