Try/Catch异常从引起异常的行继续

本文关键字:异常 继续 Catch Try | 更新日期: 2023-09-27 18:06:03

当抛出异常时,我如何捕获它,然后从引起错误的行开始继续执行?

编辑:我们的程序与Indesign服务器通信,Indesign服务器一直崩溃并抛出随机的COM相关错误(这些错误与服务器本身的错误有关)。Indesign Server也需要很长时间来处理命令,所以当它崩溃时,我们希望避免重新启动执行。相反,我们希望从引起异常的行继续执行。程序中的任何一行都可能导致异常。所以严格来说,我们不能使用循环

Try/Catch异常从引起异常的行继续

当抛出异常时,如何捕获它,然后从引起错误的行开始继续执行?(不是下一行;重试引起异常的行

不要尝试那样做。你解决这个问题的方向错了。

问题是你有一个不可靠的子系统。您有一个处理不可靠子系统的策略,即重试操作直到操作成功。如果是这种情况,那么不要将逻辑放在使用子系统的业务代码中。业务线代码应该与业务逻辑有关,而不是与您选择的处理脆弱子系统的机制有关。将机制隔离到一个特定的类,使不可靠的子系统变成可靠的子系统。

也就是说,构建一个与不可靠子系统具有相同接口的代理类,并将重试逻辑隔离到该代理类中。然后,业务线代码可以使用代理类作为可靠的子系统。

也就是说,"重试直到成功"的策略可能是一个糟糕的策略。如果子系统真的坏了,而不是以某种暂时的方式破碎,那么"重试直到它工作"意味着"永远等待",而大多数用户不喜欢永远等待。例如,如果异常是由于路由器被拔掉了,而不是由于某种暂时的情况,那么坐在那里直到有人把路由器重新插上,这似乎是一个坏主意。

如果您正在寻找通用的东西,那么使用lambda就可以了。例如

public static class Exception {
  public static void Continue(Action action) {
    try {
      action();  
    } catch { 
      // Log 
    }
  }
}
Exception.Continue(() => Statement1());
Exception.Continue(() => Statement2());

我不认为这是一个理想的解决方案,但大规模使用。它会为您使用此方法的每个语句导致额外的委托分配、委托调用和方法调用。相反,我会专注于识别导致问题的函数,并为它们单独添加显式包装。

要做到这一点,您必须将任何可能在其自己的try/catch块中抛出异常的行包围起来。

所以不用

try
{
    StatementOne();  // Exception thrown here
    StatementTwo();
}
catch (SOneException) { ... }

你必须这样做:

try
{
    StatementOne();
}
catch (SOneException) { ... }
StatementTwo();

如果由于(希望是瞬态)异常而需要重试操作,您可以使用这样的方法:

public static class ExceptionHelper
{
    public static void TryNTimesAndThenThrow(Action statement, int retryCount)
    {
        bool keepTrying = false;
        do
        {
            try
            {
                statement();
                keepTrying = false;
            }
            catch (Exception)
            {
                if (retryCount > 0)
                {
                    keepTrying = true;
                    retryCount--;
                }
                else
                {
                    // If it doesn't work here, assume it's broken and rethrow
                    throw;
                }
            }
        } while (keepTrying)
    }
}

那么你可以直接写:

ExceptionHelper.TryNTimesAndThenThrow(() => MightThrowATransientException(), 3);

记住这两种方法都应该谨慎使用。前者会使您的代码相当混乱,而后者可能会花费比您想象的更多的时间(因为如果发生意外情况,通常只是提醒用户是一个更好的主意)。因此,如果您再次尝试,那么您真正期望的对瞬态异常的强调将会消失。

你可以这样做:

                //Retry logic on opening the connection
                int retries = 0;
                openconnection:
                    try
                    {
                        connection.Open();
                    }
                    catch
                    {
                        retries++;
                        //Wait 2 seconds
                        System.Threading.Thread.Sleep(2000);
                        if (retries < MAXRETRIES)
                        {
                            goto openconnection;
                        }
                        else
                        {
                            throw;
                        }
                    }

最好的解决方案是将每行放在单独的try/catch

中。

的例子:

try { function1(); } catch { }
try { function2(); } catch { }
try { function3(); } catch { }

您也可以将它们分组在一个块中

try
{
    SomeCodeHere();
    try { function1(); } catch { }
    try { function2(); } catch { }
    try { function3(); } catch { }
}
catch
{
}

我不知道c#,但这是一个javascript,可以使脚本运行多次,如果有一个错误。

try {  
  for (var i=0; (i < t && condition) || i === 0; i++) {
    //t is how many times you want the code to run.
    //condition should be true when there is an error.
    //The code you want to execute multiple times if it fails.
  }
} catch (e) {
  
  //The code you want to execute if the code still runs into an error after being repeated multiple times.
  
}

例如,下面的代码模拟了将变量设置为来自另一个服务器的响应的情况。并且,服务器在脚本第六次运行时响应。

try {
  for (var i = 0; (i < 10 && typeof response === "undefined") || i === 0; i++) {
    var response = (i === 5) ? 1 : undefined;
    if (typeof response === "undefined") {console.log("ERROR!! #" + i)} else {console.log("Success!! #" + i)};
    if (i === 9 && typeof response === "undefined") {throw new Error("Fail to get response from other server")};
  }
} catch (e) {
  console.log("Error Message: '" + e + "'");
}

您可以运行上面的代码来查看效果。以下是另一个服务器不响应的情况。

try {
  for (var i = 0; (i < 10 && typeof response === "undefined") || i === 0; i++) {
    var response = (i === -1) ? 1 : undefined;
    if (typeof response === "undefined") {console.log("ERROR!! #" + i)} else {console.log("Success!! #" + i)};
    if (i === 9 && typeof response === "undefined") {throw new Error("Fail to get response from other server")};
  }
} catch (e) {
  console.log("Error Message: '" + e + "'");
}

你也可以把它变成一个函数来方便地使用。

function retry(code,times,condition,errorMessage) {
  try {
    for (var i = 0; (i < times && eval(condition)) || i === 0; i++) {
      eval(code);
      if (i === times-1 && eval(condition) && typeof errorMessage !== "undefined") {throw new Error(errorMessage)};
    }
  } catch (e) {
    console.log("Error Message: '" + e + "'");
  }
}

使用函数的前两个示例。

function retry(code,times,condition,errorMessage) {
  try {
    for (var i = 0; (i < times && eval(condition)) || i === 0; i++) {
      eval(code);
      if (eval(condition)) {console.log("ERROR!! #" + i)} else {console.log("Success!! #" + i)};
      if (i === times-1 && eval(condition) && typeof errorMessage !== "undefined") {throw new Error(errorMessage)};
    }
  } catch (e) {
    console.log("Error Message: '" + e + "'");
  }
}
retry("var response = (i === 5) ? 1 : undefined;",10,"typeof response === 'undefined'","Fail to get response from other server")
retry("var response = (i === -1) ? 1 : undefined;",10,"typeof response === 'undefined'","Fail to get response from other server")

我希望这能帮助到一些人