Wish Try ... Finally ... End block needed

Widget

Well-Known Member
Licensed User
Longtime User
Coming from a Delphi background, I was surprised not to find a Try/Finally block. Even SQL scripting languages have Begin/Finally blocks.

I use this a lot to ensure code is always executed even if an exception occurs so I can close files or clean up loose ends before the rtn is exited. I know there is a Try/Catch block but that only gets executed during an exception.

Try
'Execute code here like opening files, executing HTTP etc..
Finally
'This code always gets executed even if there is an exception in the above block of code
End

I'd certainly like to see this added to a future version of B4x. It would make for more stable programs.
 

LucaMs

Expert
Licensed User
Longtime User
It would make for more stable programs

I ask my self "how".

If that block of code, inside "Finally", is executed anyway, you can write it after the Try/Catch block!

If needed (?), you can use a boolean variable to store if an exception was thrown.

B4X:
Dim ExceptionThrown As Boolean = False

Try
    ' Try something
Catch
    ExceptionThrown = True
    Log(LastException)
End Try
 
If ExceptionThrown Then
    ' ...
Else
    ' ...
End If
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Found this "explanation":

it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Maybe it means if there is a "return", "continue" or "break" (java) inside the try block.
 
Last edited:

Widget

Well-Known Member
Licensed User
Longtime User
In Delphi it is customary for the Try/Except block to look for and handle only a specific type of exception. We almost never have a Try/Except block that catches all exceptions. The Delphi program will have different Try/Except blocks in many of the parent subs as well and we want the exception to percolate up to the sub that is suppose to handle that type of exception (severity of error).

So if a low level C/S database subroutine that is 10 levels deep suddenly encounters an exception ESocketError and it can't recover from it (lost connection to database), then it is best to let a higher level sub handle the exception. So control immediately passes up to whatever parent sub has a Try/Except block that looks for ESocketError (or its exception class). All of the intervening subs will terminate executing code except for its FINALLY block which allows it to clean up its instantiated variables, close files, tables etc. and puts its house in order.

Eventually the exception will get handled by the proper Try/Except block in one of the parent subs which is to gracefully terminate the operation that it started. If there is no parent sub that handles ESocketError, then the mainline routine processes the unhandled exception by displaying the exception in a dialog window. This initiates the project manager to come running out of his office to smack the programmer upside the head with his rubber chicken in an attempt to force the programmer to handle the exception properly using code instead of upchucking the exception to the end user who then calls tech support who then calls the project manager. (Project managers need their sleep and don't like to be woken up abruptly by a call from tech support.)

So exception handling is a hierarchical process, percolating the error up to the proper sub that handles it. The Finally block is needed to clean up any process that was unexpectedly terminated along the way.

(Many a rubber chicken has given its life in the pursuit of stable code.)
 

LucaMs

Expert
Licensed User
Longtime User
It is not clear, for me (I HOPE because of my poor English :)).

I don't understand the link between a number of routines (on levels) and the Try / Catch.
Also, I think the Try / Catch blocks must be very few in a program.

However, you can emulate that Finally.
 

Widget

Well-Known Member
Licensed User
Longtime User
It is not clear, for me (I HOPE because of my poor English :)).

I don't understand the link between a number of routines (on levels) and the Try / Catch.
Also, I think the Try / Catch blocks must be very few in a program.

However, you can emulate that Finally.

The Try/Catch may be in very few B4A programs because the programs are small, but it is used all the time in Delphi, at least if you want a graceful recovery of an exception.

It can't be emulated in a large B4A program without a huge amount of additional code.

To emulate Try/Except(Catch) & Try/Finally in B4A the programmer would have to put Try/Catch blocks around all code snippets that could cause an exception and catch the exception at the line the exception occurs. This is a huge amount lot of work and makes for unreadable code. In Delphi you can delegate the exception handling to one of the parent subs using the Try/Except block while the child subs will use Try/Finally to clean up the state (close files, tables, free variables etc.) that it is responsible for. The Try/Finally may also be needed in the parent subs too because that process was interrupted by the exception and they too need to clean up their state too. Control will eventually pass up to an exception handler with the proper Try/Except to handle the exception that occurred in the child Sub.

Now if your B4A program is simple enough that its main procedure only calls subs 1 level deep, then you can get away with the existing Try/Catch block. However if you have a complicated program that calls Subs that are 5 or 10 levels deep, then you want to delegate as much of the exception handling Try/Except (Catch) to one of the parent Subs while using Try/Finally to do the clean up in the state in the Sub where the exception occurred.
 
D

Deleted member 103

Guest
In Visual Studio has long since the default,
B4X:
        Try
            ...
        Catch ex As Exception
            ...
        Finally
            ...
        End Try
but I must say that I have not missed in B4x until today.
 

LucaMs

Expert
Licensed User
Longtime User
First of all, I want to remember you that:
1) I have a lot of brain memory (about 2 bytes :D)
2) my English is almost like my Chinese :)

1) ... then I have forgotten a lot of things about VB.Net (rarely I used it, in the last... 13 years!).
I have forgotten, for example, that you can try to catch ALL types of exceptions OR some specific type. Usually, I used the first method and then I would analyze the parameter.
I have also forgotten the Finally statement, given that I did not use it.

Still I don't understand why you cannot use the "workaround" I posted in #2.

Maybe I need a your example, @Widget (pseudo code).

Meanwhile, I try some routines with VB.Net :)

[BTW I know this is only my limit, otherwise no one would have invented the statement Finally ;)]
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Meanwhile, I try some routines with VB.Net

Meanwhile, before trying with VB.Net, I found:

-------
I see that the Finally in Try .. Catch will always execute after any parts of the execution of the try catch block.


Is it any different to just skip the Finally section and just run it after, outside the try catch block?

--------

Yes, it is different. Finally will always run (barring program crash). If the function exits inside of the try catch block, or another error is thrown in either the try or the catch, the finally will still execute. You won't get that functionality not using the finally statement.
-------

"You won't get that functionality not using the finally statement".
I think this is true if you try to catch a specific execption, but you cannot do it in b4x, then any type is catched. If you use a boolean variabile as I made in #2, you can check it after the try/catch block and to me it seems the same.

Probably you want to know if a "sub-sub" was completed successfully, with no exceptions and to get this you need to return ALSO that boolean variable (or, better, you need a module variable); but how do you do the same thanks to Finally?

I must try (VB.Net) :)
 
Last edited:

b4auser1

Well-Known Member
Licensed User
Longtime User
If you have several exit points in a Sub, you have to duplicate releasing resources for each of this points. With Finally section you put releasing resources in one place within finally section.

B4X:
Sub A
Try

Open file

processing file

if ... then return

if ... then return

if ... then return

finally

Close file

End try
 

b4auser1

Well-Known Member
Licensed User
Longtime User
In my post I tried to emphasize, that finally can help even if there no any exceptions at all, but was executed the operator exit/Delphi or return/B4X.
This, If you have in your Sub several logical conditions which go away from Sub, you can avoid duplicating of resources releasing for each of this exit points.
Alternative is desctructors of objects, like in C++.
 

cimperia

Active Member
Licensed User
Longtime User
Another point is that if the Exception block re-raises an exception or raises unexpectedly another exception, the finally block will still be run. That would not be the case with a hand-coded solution, unless some heavy/ugly coding is put around it. I agree that a finally block would be very useful.
 
Top