C#: try and retry

In many situation when something fails (exception is thrown) in the try block you want to retry that again. This could be a network timeout exception, or some other resource unavailability where you expect the same piece of try block code to succeed if you execute it again.

How you do it in Ruby

Let us assume there is some networkAccess() function which sometime throws a TimeoutException. In Ruby you can write code as follows.

 begin                  # try in C#
  networkAccess()
rescue Exception => ex #same as catch (Exception ex) in c#
  retry
  puts "Finally quiting"
end

Here the retry keyword makes the preceeding try block (starting with begin in case of Ruby) to be executed again. This code can be further enhanced to create a custom Exception class which has a public attribute which is used to inform the caller whether it can call the failing routine again. In ruby this'd be

 class TimeoutException < Exception
  attr  :okToRetry       # public attribute in C#
  def initialize(value) # constructor in c#
    @okToRetry = value
  end
end
// simulate a network access failure which succeeds on 3rd attempt


def networkAccess()
  $val += 1
  raise TimeoutException.new($val < 3)  #throw new TimeoutException
end

$val = 0
begin
  networkAccess()
rescue TimeoutException => ex #catch (TimeoutException ex)
  retry if ex.okToRetry
  puts "Finally quiting"
end

Here the failing callee function networkAccess raises (throws) an exception using a public attribute in the exception class to signal the caller to indicate if it can be called again.

In C#

In C# unfortunately (??) there is no support for retry. We can debate whether it'd be useful, but I feel it would make the exception handling more complete and expressive if it did. There are two workarounds. One is using goto :) and other is what we notmally use, by converting the exception to a return value and calling the failed routine again based on that.

 TryLabel: try{    downloadMgr.DownLoadFile("file:///server/file", "c:\\file");    Console.WriteLine("File successfully downloaded");}catch (NetworkException ex){    if (ex.OkToRetry)        goto TryLabel; }

If you compare this with the retry in Ruby the difference in the expressiveness is evident.

The other options is to create a wrapper around this call and convert the exception to some return code and call that wrapper again based on whether its ok to call the failing function

 public static bool Wrapper(DownloadManager downloadMgr){    try    {        downloadMgr.DownLoadFile("file:///server/file", "c:\\file");        return true;    }    catch (NetworkException ex)    {        Console.WriteLine("Failed to download file: {0}", ex.Message);        return (!ex.OkToRetry);    } }static void Main(string[] args){    while  (!Wrapper(downloadMgr)) ; }

Here the wrapper converts the failure in DownloadFile to false return code and the caller goes on calling wrapper as long as return code is false.