繁体   English   中英

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

[英]How to in case of timeout to execute method again and again until it completes successfully?

我有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    
    }

但这只是一个想法,更要确保这是处理此问题的正确方法。

您已经很接近可以在伪代码中进行更正了,并且有很多方法可以做到这一点,但是这是我的方法:

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

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

假定您的方法返回true表示成功,返回false表示时间失败(并且可能返回任何其他类型的失败的异常)。 尽管我在这里没有做过,但我强烈建议您进行一些尝试计数,以确保它不会永远循环下去。

当然,可以使用不同的超时或放弃选项来或多或少地优雅地完成此操作-但是要实现您想要的目的,一种简单的方法是定义一个重试方法,该方法将重试动作直到成功:

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次重试后放弃,或者以成倍增加的重试时间退却-您将需要定义它,因为我们对您的问题域了解不足,无法做出决定。

使用TransactionScope来确保一切都作为一个单元执行。 此处的更多信息: 使用事务范围实现隐式事务

您永远不应无限期地重试超时操作,否则可能最终导致服务器挂起或无限循环,或同时发生这两种情况。 在退出之前,应该始终有一个可接受的重试次数的阈值。

样品:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM