Simple Try/Finally Example
What is "try/finally"?
The "try/finally" programming paradigm is a way to "try" to do some actions, with some "finally" actions that you can guarantee will always happen, even if the actions in the "try" section fail, or exit, or whatever. Usually we're talking about having some sort of "cleanup" actions in the "finally".
Here's the example we'll be using here:
We show the progress window in line #1, and we want to make sure it gets closed no matter what.
So with the use of try/finally, line #9 will always happen, regardless of whether the lines 3-7 succeed, fail, or anything else.
When would I need to use a "try/finally"?
Anytime you have "cleanup" actions that need to get performed, no matter how the macro ends.
Keyboard Maestro
Keyboard Maestro doesn't have a native "try/finally" action (yet), but we can roll one ourselves, and it's surprisingly simple and effective.
TRY
Here's a simple "try" macro, using our example logic from above. The "green" actions are the ones you would replace:
- Lock a semaphore using our UUID (unique identifier) as the name†.
- Display the progress bar. Or whatever you need to protect in a "finally" section.
- Execute our "Finally" macro asynchronously‡, passing the name of the semaphore (which in this case is our UUID).
- Do whatever we want our macro to do.
† Semaphore names just need to be unique. We're using our macro's UUID because we know it's unique. We could have named it "Ralph" and it would still work, as long as another macro didn't want to use a semaphore named "Ralph" for a different purpose.
‡ Asynchronous, from the wiki:
You can optionally configure the action to be Asynchronous, which means the sub-macro will be executed as a new execution instance, and the current macro will continue on without waiting so that both macros will be executing at the same time.
FINALLY
The "Finally" macro does cleanup work, which in this case means closing the progress bar.
Here's our simple "Finally" macro:
- This is the key action. It tries to lock the semaphore, using the name passed in our trigger value. But the semaphore is already locked by the "try" macro. So the "finally" macro waits† until the semaphore is available. The semaphore will become available when the "try" macro ends - no matter how it ends.
- Once the "try" macro ends, the "finally" macro will close the progress bar.
† Having a macro wait on a semaphore uses practically no CPU resources. It is extremely efficient.
Using the Examples:
Just replace the green actions with whatever you want.
Source Macros:
There's two sets of "try" and "finally" macros in this file. One set doesn't have any comments, to make it simpler to follow. The other set has lots of comments, so if you have questions, check out those comments first.