Fog Creek Software
Discussion Board




Welcome! and rules

Joel on Software

C# Exception Question

Backround: I have an ASP.NET web page that sends an email to a user. Sometimes the SMTP Server is unavailable and an exception is encountered. I would like to have my code try to send the email 3 times before any message is presented to the user. How can I do this in a Try Catch block?

I tried doing it this way:

try{
    sendEmail();
}
catch (Exception e){
    if(nNumberofTries < 3)
    {
      nNumberofTries ++;
      sendEmail();
    }
}
finally
{

}

But this doesn't work because if the exception happens again in the catch area the finally is triggered and the catch block never catches the subsequent calls.

Could someone help me with this? Thanks...

Genx'er
Tuesday, May 17, 2005

why not do it like this? (not checked for syntax)

private int numTries = 0;
void XYZ(){
  while(numTries < 3) {
      if(sndMail())
          break;
  }
}

private bool sndMail() {

  try{
      sendEmail();
  }
  catch (Exception e){
  numTries++;
    return(false);
}
return(true)
}

hmm?
Tuesday, May 17, 2005

Yup that worked.

Looping outside was the key...

Thanks....

Genx'er
Tuesday, May 17, 2005

Sorry, but I wouldn't have coded it like either one of your examples.  For the OP's code, you should NEVER have any branching or looping logic like that in a catch block. It should only have error code in it. As for the second post, I wouldn't declare numtries at the class level. This just makes it much more complex and prone to errors.

Here is a rewrite. I left your brace and if-statement preferences in place even though code formatted like that drives me crazy!  ;)

void XYZ(){
  int numTries = 0;
  while(numTries < 3) {
      if(sndMail())
          break;
      else
          numTries++;
  }
}

private bool sndMail() {

  try{
      sendEmail();
  }
  catch (Exception e){
    return(false);
  }
  return(true)
}

matt
Tuesday, May 17, 2005

These examples make a significant mistake. See the reference to the "Don't catch everything"  section in Jeffrey Richter's book in

http://radio.weblogs.com/0104841/2002/03/11.html

howard
Wednesday, May 18, 2005

> These examples make a significant mistake.

And can you tell me what exceptions the sendMail method can throw?  It's probably using the SmtpMail class, which doesn't document the exceptions it throws.

And next year's version will probably be modified to use the new System.Net.Mail.SmtpClient class, since SmtpMail is deprecated in .NET 2.0.  And this doesn't document the exceptions it throws either.

Or of course it could be instantiating an interface to a custom mail service using a factory, in which case you may get Reflection or Remoting exceptions.

Despite the guidelines that recommend catching explicit exception types, sometimes the only sane option is to catch System.Exception.

Joe
Wednesday, May 18, 2005

SmtpMail wraps around the CDOSYS component.
It usually throws a System.Web.HttpException, if I'm not mistaken.

Tharsan
Wednesday, May 18, 2005

> SmtpMail wraps around the CDOSYS component.
> It usually throws a System.Web.HttpException, if I'm not mistaken.

As it happens, you're right, as can be confirmed using reflection (e.g. Lutz Reflector).

But
a) Can you rely on other implementations to do the same: .NET (thankfully) doesn't have java-style checked exceptions.
b) WTF is an HttpException: why is Http relevant to sending mail?
c) In order to throw an HttpException ... the SmtpMail implementation has to catch System.Exception, thus ignoring the guidelines: QED

Joe
Wednesday, May 18, 2005

The examples in Richter's book are

OutOfMemoryException
StackOverflow Exception
ExecutionEngineException
ThreadAbortException

howard
Thursday, May 19, 2005

*  Recent Topics

*  Fog Creek Home