如何在超时的情况下反复执行方法直到成功完成?

时间:2011-09-20 18:46:19

标签: c# asp.net

我有asp.net应用程序。业务层中的所有业务逻辑。

以下是方法的示例

public void DoSomething()
{
        PersonClass pc = new PersonClass();

        pc.CreatePerson();
        pc.AssignBasicTask();
        pc.ChangePersonsStatus();
        pc.CreateDefaultSettings();    
}

偶尔会发生什么,其中一个子方法可能会超时,因此该过程可能会不完整。

我认为在这种情况下确保所有步骤正确完成

public void DoSomething()
    {
            PersonClass pc = new PersonClass();
            var error = null;

            error =  pc.CreatePerson();

            if(error != timeout exception)                  
             error = pc.AssignBasicTask();
            else
              return to step above

            if(error != timeout exception)
              error = pc.ChangePersonsStatus();
            else
              return to step above

            if(error != timeout exception)
              error = pc.CreateDefaultSettings();
            else
              return to step above    
    }

但这只是一个想法,更确定它是如何处理这个问题的正确方法。

3 个答案:

答案 0 :(得分:2)

你的psuedo代码中你已经非常接近正确了,并且有很多方法可以做到这一点,但是我会这样做:

PersonClass pc = new PersonClass();
while(true)
   if(pc.CreatePerson())
      break;

while(true)
   if(pc.AssignBasicTask())
      break;

这假定您的方法返回true表示成功,false表示timeoiut失败(可能是任何其他类型失败的例外)。虽然我没有在这里做,但我强烈建议尝试一些尝试,以确保它不会永远循环。

答案 1 :(得分:2)

当然,这可以或多或少地优雅地完成,具有不同的超时或放弃选项 - 但是实现所需的简单方法是定义重试方法,该方法一直重试动作,直到成功为止:

public static class RetryUtility 
{
    public T RetryUntilSuccess<T>(Func<T> action) 
    {
        while(true) 
        {
            try 
            {
                return action();
            }
            catch 
            {
                // Swallowing exceptions is BAD, BAD, BAD. You should AT LEAST log it.
            }
        }
    }

    public void RetryUntilSuccess(Action action) 
    {
        // Trick to allow a void method being passed in without duplicating the implementation.
        RetryUntilSuccess(() => { action(); return true; });
    }
}

然后做

    RetryUtility.RetryUntilSuccess(() => pc.CreatePerson());
    RetryUtility.RetryUntilSuccess(() => pc.AssignBasicTask());
    RetryUtility.RetryUntilSuccess(() => pc.ChangePersonsStatus());
    RetryUtility.RetryUntilSuccess(() => pc.CreateDefaultSettings());   

我必须敦促你思考如果方法失败会怎么做,你可能会创建一个无限循环 - 也许它应该在N重试后放弃或者以指数方式提高重试时间后退 - 你需要定义它,因为我们无法充分了解您的问题域来决定。

答案 2 :(得分:0)

使用TransactionScope确保所有内容都作为一个单元执行。更多信息:Implementing an Implicit Transaction using Transaction Scope

你永远不应该无限次地重试超时操作,你最终可能会挂起服务器或无限循环或两者兼而有之。在退出之前,应始终存在可接受的重试次数的阈值。

样品:

using(TransactionScope scope = new TransactionScope())
{
   try
   {
      // Your code here

      // If no errors were thrown commit your transaction
      scope.Complete();          
   }
   catch
   {
      // Some error handling
   }
}