I have in my application a procedure that handles the generated exceptions. It turns out that if the exception is generated in untThreadDSR, the exception is not being captured by the procedure to which it should also manipulate it. If the exception is generated from any other form, the procedure captures it correctly.
The procedure is in the main DataModule:
...
private
{ Private declarations }
procedure HandleExceptions(Sender: TObject; E: Exception);
...
procedure DM.HandleExceptions(Sender: TObject; E: Exception);
begin
if pos('UNIQUE KEY',E.Message) <> 0 then
begin
if pos('UNQ_CUSTOMER_NAME',E.Message) <> 0 then
MsgMsg('Customer already registered.',2)
else if pos('UNQ_USERS_LOGIN',E.Message) <> 0 then
MsgMsg('User already registered.',2);
end else
if pos('ERROR_DATASYS',E.Message) <> 0 then
MsgMsg('The Server Date is incorrect. Please contact your network administrator!',2)
else //Other messages will be sent to Support
SendReport(E.Message, V_COMPANY, V_LOGIN, V_APP_VERSION, Sender);
end;
untThreadDSR:
unit untThreadDSR;
interface
uses
Classes, SysUtils, Messages, Windows, Forms;
type
TThreadDSR = class(TThread)
procedure DSR_Start;
private
{ Private declarations }
protected
procedure Execute; override;
end;
implementation
uses untDM;
procedure TThreadDSR.DSR_Start;
begin
//I put this intentionally just to generate an exception
StrToInt('');
//If this is on any other form, the exception is caught by "HandleExceptions", but from here on out!
end;
procedure TThreadDSR.Execute;
begin
Synchronize(DSR_Start);
end;
end.
TThreadDSR is called as follows:
procedure TFrmDSR.btnExecuteClick(Sender: TObject);
var
Thread: TThreadDSR;
begin
Thread := TThreadDSR.Create(true);
Thread.FreeOnTerminate := true;
Thread.Resume;
end;
Exceptions don't cross thread boundaries. If an uncaught exception escapes the procedure called by TThread.Synchronize()
, Synchronize()
captures the exception and re-raises it in the context of the worker thread. If Execute()
subsequently does not catch the exception, the thread will terminate and assign the exception to the TThread.FatalException
property.
You can use the TThread.OnTerminate
event (which is called in the context of the main thread) to pass the FatalException
to your HandleExceptions()
procedure.