如果第一个请求失败,请重试该请求

时间:2009-06-26 11:55:33

标签: c# web-services

我在我的网络应用程序上使用xml Web服务,有时远程服务器无法及时响应。如果第一次尝试失败,我想出了重新请求的想法。为了防止循环,我想在2处限制并发请求。我想得到一个意见,如果我在下面做了什么,并且会按照我的预期工作。

public class ScEngine
{
    private int _attemptcount = 0;
    public int attemptcount
    {
        get
        {
            return _attemptcount;
        }
        set
        {
            _attemptcount = value;
        }
    }

    public DataSet GetStat(string q, string job)
    {

        try
        {
           //snip....
            attemptcount += attemptcount;
            return ds;

        }
        catch
        {
            if (attemptcount>=2)
            {
           return null;
            }
            else
            {
                return GetStat(q, job);
            }

        }

    }
}

6 个答案:

答案 0 :(得分:1)

您忘记增加尝试次数。另外,如果第二次运行时出现任何错误,则不会被捕获(因此,将成为未处理的异常)。

答案 1 :(得分:1)

public class ScEngine
{
    public DataSet GetStat(string q, string job)
    {
        int attemptCount;
        while(attemptCount < 2)
        {
            try
            {
                attemptCount++;
                var ds = ...//web service call
                return ds;
            }
            catch {}
        }
        //log the error
        return null;
    }
}

答案 2 :(得分:1)

查看此链接。这是处理重试和超时的好方法。 http://timross.wordpress.com/2008/02/10/implementing-the-circuit-breaker-pattern-in-c/

答案 3 :(得分:0)

我不会为了重试而递归。此外,我不会抓住并忽略所有异常。我将了解哪些异常表明应该重试的错误,并且会捕获这些错误。正如你的代码所代表的那样,你将忽略严重的错误。

答案 4 :(得分:0)

你不想这样解决它。您只需在服务器上施加更多负载并导致更多超时。

您可以增加网络服务超时via httpRuntime。 Web服务通常会在一次调用中返回大量数据,因此我发现自己经常这样做。不要忘记增加客户愿意在客户端等待的时间。

答案 5 :(得分:0)

这是一个不使用递归但实现相同结果的版本。它还包括一个延迟,因此如果它打嗝,你可以给服务器恢复时间。

    /// <summary>
    /// The maximum amount of attempts to use before giving up on an update, delete or create
    /// </summary>
    private const int MAX_ATTEMPTS = 2;

    /// <summary>
    /// Attempts to execute the specified delegate with the specified arguments.
    /// </summary>
    /// <param name="operation">The operation to attempt.</param>
    /// <param name="arguments">The arguments to provide to the operation.</param>
    /// <returns>The result of the operation if there are any.</returns>
    public static object attemptOperation(Delegate operation, params object[] arguments)
    {
        //attempt the operation using the default max attempts
        return attemptOperation(MAX_ATTEMPTS, operation, arguments);
    }

    /// <summary>
    /// Use for creating a random delay between retry attempts.
    /// </summary>
    private static Random random = new Random();

    /// <summary>
    /// Attempts to execute the specified delegate with the specified arguments.
    /// </summary>
    /// <param name="operation">The operation to attempt.</param>
    /// <param name="arguments">The arguments to provide to the operation.</param>
    /// <param name="maxAttempts">The number of times to attempt the operation before giving up.</param>
    /// <returns>The result of the operation if there are any.</returns>
    public static object attemptOperation(int maxAttempts, Delegate operation, params object [] arguments)
    {
        //set our initial attempt count
        int attemptCount = 1;

        //set the default result
        object result = null;

        //we've not succeeded yet
        bool success = false;

        //keep trying until we get a result
        while (success == false)
        {
            try
            {
                //attempt the operation and get the result
                result = operation.DynamicInvoke(arguments);
                //we succeeded if there wasn't an exception
                success = true;
            }
            catch
            {
                //if we've got to the max attempts and still have an error, give up an rethrow it
                if (attemptCount++ == maxAttempts)
                {
                    //propogate the exception
                    throw;
                }
                else
                {
                    //create a random delay in milliseconds
                    int randomDelayMilliseconds = random.Next(1000, 5000);
                    //sleep for the specified amount of milliseconds
                    System.Threading.Thread.Sleep(randomDelayMilliseconds);
                }
            }
        }

        //return the result
        return result;
    }