Продолжайте пытаться общаться с сервером, когда интернет не работает - PullRequest
6 голосов
/ 05 августа 2011

Таким образом, мое приложение обменивается запросами / ответами с сервером (без проблем), пока интернет-соединение не прервется на пару секунд, а затем не вернется.Затем код, подобный этому:

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 продолжает выдавать исключение, даже когда Интернет возвращается.

Что я делаю неправильно?Есть ли другой способ исправить это?

Спасибо!

Ответы [ 3 ]

17 голосов
/ 05 августа 2011

Вы должны заново создавать запрос каждый раз, и вы должны выполнять повторы в цикле с ожиданием между каждой повторной попыткой. Время ожидания должно постепенно увеличиваться с каждой ошибкой.

* 1003 Е.Г. *

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 голос
/ 05 августа 2011

Я думаю, что вы пытаетесь сделать это:

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 час).

0 голосов
/ 05 августа 2011

Если он все еще делает это, когда вы восстанавливаете соединение - тогда я предполагаю, что он просто возвращает тот же результат снова.

Возможно, вы захотите каждый раз заново создавать запрос, кроме этогоЯ не вижу ничего плохого в коде или логике.Помимо того, что вы навсегда блокируете эту тему.Но тогда это может быть хорошо, если это сам по себе рабочий поток.

...