try- catch

L

Luke Davis

I'm new so bear with me. Is there a way for the catch to fix a problem
then start the try over again?

For example, I have this console application sync a remote database and it
takes hours. Sometimes the link, for no apparent reason will drop and will
trigger the catch. I want the catch to wait a minute then start the try
over again. Possible? or not?

Luke
 
A

Andrew Faust

Sure. Just structure your code in such a way to support that. For example
if your oringal method looked like this:

void Foo()
{
<Do stuff>

Try {
<DoDB Stuff>
} catch {}

<Do More Stuff>
}

You could rewrite it like this:

void Foo()
{
<Do Stuff>
while (!DoDBStuff())
{
Thread.Sleep(1000);
}
<Do More Suff)
}

bool DoDBStuff()
{
try{
<DoDB Stuff>
return true;
} catch {
return false;
}
}

Note, you wouldn't want to do leave the while loop like that as it could
become an infinite loop. You'd most likely want to put some counter in
there to kick out of the loop after so many retries. You'd then need to
check to see if it ever succeeded and probably throw an exception instead
of "Doing more stuff" in the event that it never succeeded.

You also want to be careful with Thread.Sleep. It will let you pause before
resuming. However, if this is running in your main thread it will freeze
the applications UI as well.
 
L

Luke Davis

Thanks,

After the Thread.sleep do I need to call foo() again? within foo?


Andrew Faust said:
Sure. Just structure your code in such a way to support that. For example
if your oringal method looked like this:

void Foo()
{
<Do stuff>

Try {
<DoDB Stuff>
} catch {}

<Do More Stuff>
}

You could rewrite it like this:

void Foo()
{
<Do Stuff>
while (!DoDBStuff())
{
Thread.Sleep(1000);
}
<Do More Suff)
}

bool DoDBStuff()
{
try{
<DoDB Stuff>
return true;
} catch {
return false;
}
}

Note, you wouldn't want to do leave the while loop like that as it could
become an infinite loop. You'd most likely want to put some counter in
there to kick out of the loop after so many retries. You'd then need to
check to see if it ever succeeded and probably throw an exception instead
of "Doing more stuff" in the event that it never succeeded.

You also want to be careful with Thread.Sleep. It will let you pause
before resuming. However, if this is running in your main thread it will
freeze the applications UI as well.

--
Andrew Faust
andrew[at]andrewfaust.com
http://www.andrewfaust.com


Luke Davis said:
I'm new so bear with me. Is there a way for the catch to fix a problem
then start the try over again?

For example, I have this console application sync a remote database and
it takes hours. Sometimes the link, for no apparent reason will drop
and will trigger the catch. I want the catch to wait a minute then
start the try over again. Possible? or not?

Luke
 
P

Peter Duniho

After the Thread.sleep do I need to call foo() again? within foo?

No. Using the code he proposed, the method that is catching the
exception returns true or false depending on whether the exception
happened or not. The while() loop causes that method to be called
repeatedly until it returns true. That is sufficient for the purpose
of repeating the operation with a 1 second delay between attempts.

That said, there are any number of alternative means for accomplishing
this sort of thing. The suggestion was just one example. The general
idea is always going to be the same though: catching the exception
doesn't preclude you being able to go back and try the operation
again. The only requirement is that the try/catch block can't
intersection with flow-control statements, just as other kinds of
blocks in the code can't intersect with each other.

The only thing unusual about a try/catch block as compared to other
block constructs is that flow can jump from one block to the other
(but still only within the same try/catch clause). Other than that,
retrying an operation after it fails in a try/catch block is pretty
much exactly the same as you'd do it in any other context.

Pete
 
A

Andrew Faust

No, because it's in a loop. Keep in mind that you won't want to implement
it exactly like this. I put out just a simple example to show the concept,
however, there are some issues you'd need to deal with. The biggest issue
is the fact that it can get in an infinite loop if DoDBStuff never
succeeds. In reality you should probably inspect the exception that was
thrown. Some exceptions like connection timeouts are acceptable to just
retry the operation. However, some exceptions may indicate an issue that
will cause it to never succeed. For example, if you were performing an
insert and you tried to set an Int field to 'Bob', that will obviously
always throw an exception no matter how many times you try it. I'd
recommend catching only the exceptions you want to retry and continue
throwing the insurmountable errors.

--
Andrew Faust
andrew[at]andrewfaust.com
http://www.andrewfaust.com


Luke Davis said:
Thanks,

After the Thread.sleep do I need to call foo() again? within foo?


Andrew Faust said:
Sure. Just structure your code in such a way to support that. For
example if your oringal method looked like this:

void Foo()
{
<Do stuff>

Try {
<DoDB Stuff>
} catch {}

<Do More Stuff>
}

You could rewrite it like this:

void Foo()
{
<Do Stuff>
while (!DoDBStuff())
{
Thread.Sleep(1000);
}
<Do More Suff)
}

bool DoDBStuff()
{
try{
<DoDB Stuff>
return true;
} catch {
return false;
}
}

Note, you wouldn't want to do leave the while loop like that as it could
become an infinite loop. You'd most likely want to put some counter in
there to kick out of the loop after so many retries. You'd then need to
check to see if it ever succeeded and probably throw an exception
instead of "Doing more stuff" in the event that it never succeeded.

You also want to be careful with Thread.Sleep. It will let you pause
before resuming. However, if this is running in your main thread it will
freeze the applications UI as well.

--
Andrew Faust
andrew[at]andrewfaust.com
http://www.andrewfaust.com


Luke Davis said:
I'm new so bear with me. Is there a way for the catch to fix a
problem then start the try over again?

For example, I have this console application sync a remote database and
it takes hours. Sometimes the link, for no apparent reason will drop
and will trigger the catch. I want the catch to wait a minute then
start the try over again. Possible? or not?

Luke
 
M

Mr. Arnold

Luke Davis said:
I'm new so bear with me. Is there a way for the catch to fix a problem
then start the try over again?

For example, I have this console application sync a remote database and it
takes hours. Sometimes the link, for no apparent reason will drop and
will trigger the catch. I want the catch to wait a minute then start the
try over again. Possible? or not?

Luke

You could just use a global flag. The method that calls this database
method should be made to wait.

You set the flag in the database method on its try/catch --- the catch and
you clear the Exception by setting it to null and come out of the method
back to the method that called it.

Since you cleared the Exception, if the method that made the call to the
database method had a try/catch in calling the database method, then it's
not going to take the catch path. It's going to comeback to the last line in
the try.

It's at this point in the try that you check for the flag. If the flag is
set, then you wait a minute and then you make the call to the database
method again ----- try it again. You might want to set some kind of count
and check the count and stop after so many retries.
 
A

almir

I'm new so bear with me. Is there a way for the catch to fix a problem
then start the try over again?

For example, I have this console application sync a remote database and it
takes hours. Sometimes the link, for no apparent reason will drop and will
trigger the catch. I want the catch to wait a minute then start the try
over again. Possible? or not?

Luke

hi,
I alway use goto for this, this is probably the only place wher it is
ok to use goto (if you do not like goto at all pleas contact the
langauge-author)
below you will find a snippet


int nrOfTries=0;

//goto is used here to do up to max_nr_of_connection_retries
//to hide genneral network error
START:

SqlConnection result = new SqlConnection(ConnecectionString);
int connectionTimeoutWas=result.ConnectionTimeout;

try
{
result.Open();
string commandText="select 'TEST CONNECTION' ";
SqlCommand test= new SqlCommand(commandText, result);
test.CommandTimeout=2;
//we do not care about results , only to see if exception occures
test.ExecuteNonQuery();
}
catch(Exception e)
{
nrOfTries++;
result.Close();
result.Dispose();
if(nrOfTries<=MAX_NR_OF_TRIES_FOR_CONNECTION)
{
ErrorHandling.ExceptionFormater form= new
ErrorHandling.ExceptionFormater(e);
Notifications.Notify.Warning(result, "dead connection found in
getOpenConnection current try#"
+nrOfTries +Global.NEW_LINE+form.FormatedException);
goto START;
}
else
{
throw new ApplicationException("To many attempts made in
GetOpenConnection current try#"
+ nrOfTries, e);
}
}

//result.ConnectionTimeout=connectionTimeoutWas;
return result;
 
L

Luke Davis

Thanks everyone for your support, I'll be trying all of these ideas to see
which one works the best in my situation.

As for the goto I thought it can only call a marker below itself, in your
example you're telling it to go to the top of the code and start over, I'm
not near the computer with those files on it right now to try it out, but
that can be done right?
 
L

Lew

almir said:
I alway use goto for this, this is probably the only place wher it is
ok to use goto (if you do not like goto at all pleas contact the
langauge-author)
below you will find a snippet

I do not agree that this represents a valid use of goto; in particular it
should not be used for non-local exits from a block. That's the purpose of
throwing an exception in the first place. I rate this example of goto as an
antipattern.

Others have shown a better idiom for the OP's purpose.

As an exercise, in languages that support goto, I try to justify its use every
so often in some piece of code. Nearly always a better, more reliable, more
extensible, clearer idiom replaces it.

P.S., code posts are more readable if spaces are used to indent instead of TAB
characters. Two to four spaces per indent level is sufficient for Usenet.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top