Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在超时的情况下一次又一次地执行方法,直到它成功完成?_C#_Asp.net - Fatal编程技术网

C# 如何在超时的情况下一次又一次地执行方法,直到它成功完成?

C# 如何在超时的情况下一次又一次地执行方法,直到它成功完成?,c#,asp.net,C#,Asp.net,我有asp.net应用程序。业务层中的所有业务逻辑 下面是该方法的示例 public void DoSomething() { PersonClass pc = new PersonClass(); pc.CreatePerson(); pc.AssignBasicTask(); pc.ChangePersonsStatus(); pc.CreateDefaultSettings(); } 偶尔发生的事情

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

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

使用
事务处理范围来确保所有事情都作为一个单元执行。更多信息请点击此处:

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

样本:

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

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

您的psuedo代码中的代码非常接近于正确,有很多方法可以做到这一点,但下面是我将如何做到这一点:

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

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

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

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

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; });
    }
}

我必须敦促您考虑,如果该方法不断失败,您可能会创建一个无限循环-也许它应该在N次重试后放弃,或者以指数方式增加重试时间-您需要定义它,因为我们对您的问题域了解不够,无法做出决定。

您需要修复超时问题。重试只会增加流量并增加问题。您可能缺少一个数据库索引。我们有索引,这种情况很少发生。也许每1000人一次transaction@TheCodeKing假设超时是由于数据库或数据库问题造成的;如果他正在使用REST服务或WCF服务或类似的服务,那么在这种情况下,超时可能会由于多种原因而发生。这真的没有意义。按照设计,您的应用程序将永远尝试执行该过程。如果你决定这样做(我认为你应该重新考虑),你应该将超时设置为无限。至少在这种情况下,这个过程有你愿意让它运行的所有时间。如果某件事情超时,并不一定意味着它不能成功完成。这意味着你的电话在一段特定的时间内没有发现是否成功。考虑在代码中不断重复超时的可能性。它不涉及数据库中涉及的任何地方。@ DRISIS:@ ScottE,数据库仍然是大多数人都知道使用它的。另外,在查看相关的代码时,我敢打赌没有使用
IEnlistmentNotification
的自定义实现。这只是因为大多数人不知道在非数据库场景中使用它并不意味着它不是有效的解决方案。这里的重点是为提出问题的人提供一些替代方案。他们可以自己决定哪一个适合他们。谁知道呢,有人可能真的学到了一些东西!我每天都从自己的问答中学到一些新东西。干杯
    RetryUtility.RetryUntilSuccess(() => pc.CreatePerson());
    RetryUtility.RetryUntilSuccess(() => pc.AssignBasicTask());
    RetryUtility.RetryUntilSuccess(() => pc.ChangePersonsStatus());
    RetryUtility.RetryUntilSuccess(() => pc.CreateDefaultSettings());