在没有goto的情况下编写重试逻辑的更好方法

时间:2010-11-10 20:42:46

标签: c# .net goto

有没有更好的方法来编写此代码而不使用goto?这看起来很尴尬,但我想不出更好的方法。我需要能够执行一次重试尝试,但我不想复制任何代码。

public void Write(string body)
{
    bool retry = false;
RetryPoint:
    try
    {
        m_Outputfile.Write(body);
        m_Outputfile.Flush();
    }
    catch (Exception)
    {
        if( retry )
            throw; 
        // try to re-open the file...
        m_Outputfile = new StreamWriter(m_Filepath, true);
        retry = true;
        goto RetryPoint;
    }
}

7 个答案:

答案 0 :(得分:15)

这是我将使用的基本逻辑,而不是goto语句:

bool succeeded = false;
int tries = 2;

do
{
    try
    {
        m_Outputfile = new StreamWriter(m_Filepath, true);
        m_Outputfile.Write(body); 
        m_Outputfile.Flush(); 
        succeeded = true;
    }
    catch(Exception)
    {
        tries--;
    }
}
while (!succeeded && tries > 0);

我刚刚添加了尝试逻辑,即使原始问题没有。

答案 1 :(得分:5)

迈克尔的解决方案并不能完全满足要求,即重试固定次数,抛出最后一次失败。

为此,我建议使用简单的for循环,倒计时。如果成功,请退出break(或者,如果方便的话,返回)。否则,让catch检查索引是否为0。如果是,请重新抛出而不是记录或忽略。

public void Write(string body, bool retryOnError)
{
    for (int tries = MaxRetries; tries >= 0; tries--)
    {
        try
        {
            _outputfile.Write(body);
            _outputfile.Flush();
            break;
        }
        catch (Exception)
        {
            if (tries == 0)
                throw; 

            _outputfile.Close();
            _outputfile = new StreamWriter(_filepath, true);
        }
    }
}

在上面的示例中,返回会很好,但我想展示一般情况。

答案 2 :(得分:4)

@Michael's answer(使用正确实现的catch块)可能是最容易使用的,并且是最简单的。但是为了提出替代方案,这里有一个版本将“重试”流量控制分解为一个单独的方法:

// define a flow control method that performs an action, with an optional retry
public static void WithRetry( Action action, Action recovery )
{
    try {
        action(); 
    }
    catch (Exception) {
        recovery();
        action();
    }
}

public void Send(string body)
{
    WithRetry(() =>
    // action logic:
    {
       m_Outputfile.Write(body);
       m_Outputfile.Flush();
    },
    // retry logic:
    () =>
    {
       m_Outputfile = new StreamWriter(m_Filepath, true);
    });
}

当然,您可以通过重试计数,更好的错误传播等方式来改善这一点。

答案 3 :(得分:1)

如果你把它放在一个循环中怎么办?也许与此类似的东西。

while(tryToOpenFile)
{
    try
    {
        //some code
    }
    catch
    {
    }
    finally
    {
        //set tryToOpenFile to false when you need to break
    }
}

答案 4 :(得分:1)

public void Write(string body, bool retryOnError)
{
    try
    {
        m_Outputfile.Write(body);
        m_Outputfile.Flush();
    }
    catch (Exception)
    {
        if(!retryOnError)
            throw; 
        // try to re-open the file...
        m_Outputfile = new StreamWriter(m_Filepath, true);
        Write(body, false);
    }
}

答案 5 :(得分:0)

尝试以下内容:

int tryCount = 0;
bool succeeded = false;

while(!succeeded && tryCount<2){
    tryCount++;
    try{
        //interesting stuff here that may fail.

        succeeded=true;
    } catch {
    }
}

答案 6 :(得分:0)

使用布尔值

public void Write(string body)
{
        bool NotFailedOnce = true;            
        while (true)
        {
            try
            {
                 _outputfile.Write(body);
                 _outputfile.Flush();           
                 return;                    
            }
            catch (Exception)
            {
                NotFailedOnce = !NotFailedOnce;
                if (NotFailedOnce)
                {
                    throw;
                }
                else
                {
                     m_Outputfile = new StreamWriter(m_Filepath, true);
                }
            }
      }        
}