Delphi exception handling, use E: Exception or ExceptObject

There is no right way for exception handling. There is just one way. What might confuse you could be dealing with the exception object which is created, and which causes an exception to raise, but whose lifetime is the most important for you here.

In general, there's only two ways of dealing with those exception objects. Either you let them alive beyond the exception block scope and release them by yourself or let them free by the RTL when the exception block ends.

But to answer what I guess you've asked. Exception class isn't thread safe. And, your coworkers were wrong as no one is forced to use specific exception handling in threads. These rules are the same for all threads created by the process, no matter what. Just, those exception objects can be unstable within exception blocks:

1. Get the current exception object from the ExceptObject

The ExceptObject returns the current exception object. In practice, it may cause this; if you store such object reference into a variable inside an exception handler block and another exception will get raised within such block, that stored instance may become invalid. Which is quite unsafe.

But it doesn't mean you could not take a reference of such object and pass it to another thread by using some synchronization mechanisms (since it's not a thread safe class) and work with it there. You just need to take care that no other exception will be raised because that would invalidate the previously stored object so as you must take care of staying inside the exception handler from the caller's point of view and you must use a kind of thread synchronization mechanism.

So actually working with the exception object acquired from an on expression can be more stable than using ExceptObject. But the same rules applies here as well; you'd need to synchronize the object instance from the on expression with another thread (since it's not a thread safe class), but in such case, object acquired from the on expression won't get changed unlike the ExceptObject one can be within a certain exception block.

2. Retain exception object by using AcquireExceptionObject

The AcquireExceptionObject function allows you to keep the exception object alive even out of the exception block.

For an exception handling when speaking about thread synchronization, I'd suggest you using the AcquireExceptionObject function which makes the exception object free to consume, even after the exception block ends. For you that brings the only responsability, free such acquired object by calling the ReleaseExceptionObject procedure or raising the exception by this object again.


Victoria is absolutely correct.

Personally, I have a strong preference for this idiom:

try
  ...
   except
     // IO error
     On E : EInOutError do
       ShowMessage('IO error : '+E.Message);
     // Division by zero
     On E : EDivByZero do
       ShowMessage('Div by zero error : '+E.Message);
     // Catch other errors
     else
       ShowMessage('Unknown error');
   end;

To elaborate:

  1. Victoria said "There is no right way for exception handling. There is just one way." That's absolutely correct.

  2. The advice you got about "use one syntax for threads, and the other for GUIs" is simply wrong. There is no "different syntax" for "threads" vs. "GUI". That's nonsense :(

  3. I prefer using on : MyExceptionType in an exception block.

  4. I also prefer to differentiate different exception types, whenever/wherever possible.

  5. The example you cited, http://edn.embarcadero.com/article/10452, deals with how to avoid a possible access violation if you don't handle the exception within that particular thread. Saving the exception instance in a member variable helps mitigate this problem.

The following link might help clarify:

  • http://www.delphibasics.co.uk/Article.asp?Name=Exceptions