Reputation: 13345
I have for habit to execute anonymous thread like :
TThread.CreateAnonymousThread(
procedure
begin
.....
end).start;
But the problem is that if some unhandled exception will raise during the execution, then i will be not warned about it! For the main thread we have Application.OnException
. Do we have something similar for background thread ?
Upvotes: 6
Views: 1637
Reputation: 13345
Ok, finally I got the best answer :
Assign the global ExceptionAcquired
procedure to our own implementation (it is nil by default). This procedure gets called for unhandled exceptions that happen in other threads than the main thread.
ExceptionAcquired := MyGlobalExceptionAcquiredHandler;
Upvotes: 1
Reputation: 13345
The answer of J... and Remy Lebeau are good with what delphi offer, but i need a little more and I finally decide to modify a little the unit System.Classes
var
ApplicationHandleThreadException: procedure (Sender: TObject; E: Exception) of object = nil;
function ThreadProc(const Thread: TThread): Integer;
...
try
Thread.Execute;
except
Thread.FFatalException := AcquireExceptionObject;
if assigned(ApplicationHandleThreadException) and
assigned(Thread.FFatalException) and
(Thread.FFatalException is Exception) and
(not (Thread.FFatalException is EAbort)) then
ApplicationHandleThreadException(Thread, Exception(Thread.FFatalException));
end;
in this way you just need to assign ApplicationHandleThreadException
to handle unhandled exception raise in any TThread. You don't need to be worry about the multi thread because global var like ExceptAddr
are declared as threadvar
so everything work fine, even to retrieve the stack trace !
https://quality.embarcadero.com/browse/RSP-21269
Upvotes: -1
Reputation: 595632
TThread
has a public FatalException
property:
If the
Execute
method raises an exception that is not caught and handled within that method, the thread terminates and setsFatalException
to the exception object for that exception. Applications can checkFatalException
from anOnTerminate
event handler to determine whether the thread terminated due to an exception.
For example:
procedure TMyForm.DoSomething;
begin
...
thread := TThread.CreateAnonymousThread(...);
thread.OnTerminate := ThreadTerminated;
thread.Start;
...
end;
procedure TMyForm.ThreadTerminated(Sender: TObject);
begin
if TThread(Sender).FatalException <> nil then
begin
...
end;
end;
Upvotes: 10
Reputation: 31393
N̶o̶,̶ ̶t̶h̶e̶r̶e̶ ̶i̶s̶ ̶n̶o̶t̶h̶i̶n̶g̶ ̶s̶i̶m̶i̶l̶a̶r̶ ̶f̶o̶r̶ ̶a̶ ̶b̶a̶c̶k̶g̶r̶o̶u̶n̶d̶ ̶t̶h̶r̶e̶a̶d̶.̶ (Thanks, Remy!)
The best solution is to always be absolutely certain to never let an exception escape from a thread. Ideally, your thread procedures should look something like this :
TThread.CreateAnonymousThread(
procedure
begin
try
{ your code}
except
{on E : Exception do}
{... handle it!}
end;
end).start;
Upvotes: 6