Catch块中的重试?

时间:2011-11-09 09:30:32

标签: c# sql

如何在catch块中实现代码?

  try
    {
       // Call a MS SQL stored procedure (MS SQL 2000)
       // Stored Procedure may deadlock 
    }
    catch
    {
       // if deadlocked Call a MS SQL stored procedure (may deadlock again)
       // If deadlocked, keep trying until stored procedure executes
    }
    finally
    {

    }

7 个答案:

答案 0 :(得分:24)

不建议这样做,可能会导致程序出现严重问题。例如,如果数据库已关闭怎么办?

但是,这是如何在循环中完成的:

for(int attempts = 0; attempts < 5; attempts++)
// if you really want to keep going until it works, use   for(;;)
{
    try
    {
        DoWork();
        break;
    }
    catch { }
    Thread.Sleep(50); // Possibly a good idea to pause here, explanation below
}

更新:正如Disappointment先生在下面的评论中提到的:Thread.Sleep方法暂停执行指定的毫秒数。没有错误是完全随机的,大多数只能通过再次尝试才能正常工作,因为尝试之间的时间发生了变化。暂停执行该线程将为此提供更大的机会窗口(例如,数据库引擎启动的时间更长)。

答案 1 :(得分:3)

这样的事情

bool retry = true;
while( retry ){
  try{
    ...
    retry = false;
  }
  catch
  {
    ...
  }
  finally
  {
    ...
  }
}

只要try块的最后一行运行(retry = false),它就会继续运行。如果发生某些异常,它将运行catch并最终阻塞,然后循环备份并再次运行try块。

如果您只想尝试x次,则可以使用具有首次尝试次数的起始值的int替换重试。然后检查它是否在while循环中等于0,在循环开始时递减它,并将其设置为0作为try块的最后一行。

你当然应该对那个空的catch块做一些事情,这样它就可以捕获你预期的异常,而不是捕获所有异常的异常。

答案 2 :(得分:2)

不要在catch块中实现它。而是在它周围写一个循环重复,直到它成功或达到某个限制。

类似的东西:

bool quit = false;
int loopcount = 0;
while(!quit )
{
   try
   {
       // execute the command, might throw an exception)
       quit = true; // no exception if you got here
   }
   catch(Exception ex)
   {
      if (ex != deadlock) // doesn't work like this :-(
        quit = true;
   }
   finally
   {
      // etc.
   }
   loopcount++;
   if (loopcount > 3)
      quit = true;
}

答案 3 :(得分:2)

你真的不应该只是锤击数据库,直到它成功执行你的SP,但那是另一个故事。

你可以这样做:

Boolean succeeded = false;

while (!succeeded)
{

    try
    {
        // Call a MS SQL stored procedure (MS SQL 2000)
        // Stored Procedure may deadlock 
        succeeded = true;
    }
    catch (Exception ex)
    {
        // Log
    }
}

答案 4 :(得分:1)

可能就像在while循环中包装整个try / catch一样简单:

while (!success) {

    try
    {
       // Call a MS SQL stored procedure (MS SQL 2000)
       // Stored Procedure may deadlock 
       success = true;
    }
    catch
    {
       // if deadlocked Call a MS SQL stored procedure (may deadlock again)
       // If deadlocked, keep trying until stored procedure executes
       success = false;
    }

}

答案 5 :(得分:1)

从Microsoft Developer Network页面逐字复制他们称之为Retry Pattern

的内容
private int retryCount = 3;
...

public async Task OperationWithBasicRetryAsync()
{
  int currentRetry = 0;

  for (; ;)
  {
    try
    {
      // Calling external service.
      await TransientOperationAsync();

      // Return or break.
      break;
    }
    catch (Exception ex)
    {
      Trace.TraceError("Operation Exception");

      currentRetry++;

      // Check if the exception thrown was a transient exception
      // based on the logic in the error detection strategy.
      // Determine whether to retry the operation, as well as how 
      // long to wait, based on the retry strategy.
      if (currentRetry > this.retryCount || !IsTransient(ex))
      {
        // If this is not a transient error 
        // or we should not retry re-throw the exception. 
        throw;
      }
    }

    // Wait to retry the operation.
    // Consider calculating an exponential delay here and 
    // using a strategy best suited for the operation and fault.
    Await.Task.Delay();
  }
}

// Async method that wraps a call to a remote service (details not shown).
private async Task TransientOperationAsync()
{
  ...
}

他们会详细介绍,解释适当的用途,以及这种模式的不恰当用途。例如,如果您预计您遇到的错误是暂时性的,并且稍后再次重试可能会成功,这可能适合您。如果这是为了帮助您解决一些扩展问题,那么这不适合您。

您可能也对他们所描述的Circuit Breaker Pattern感兴趣,“处理在连接到远程服务或资源时可能需要花费不同时间来纠正的错误。”

答案 6 :(得分:0)

您可以实施计时器来检查商店程序的健康状况,并根据同事的说法在循环内部根据这些做出答案。