Important: as a general rule, you should write your application in a such way that it will behave correctly without EurekaLog on board. This means that if your or 3rd party code throws an exception in a thread - it must be handled in a way that you expect. For example, by showing an error message, canceling action, retrying, etc. Once your application behaves like it is supposed to do - then you add EurekaLog for it. EurekaLog will auto-handle all unhandled exceptions automatically (by hooking few well-known places), and for everything else - you can call EurekaLog from your own handlers when needed. In other words:
EurekaLog provides two helper routines to simplify thread management: BeginThreadEx function and TThreadEx class - which should be used instead of BeginThread function and TThread class respectively. Both routines are from EBase unit. EBase unit is a special unit that can be included in any application without including full EurekaLog code. Therefore you can safely use EBase unit in your applications even without EurekaLog enabled.
Note: when your thread is processing exception, the processing will be performed in a background thread. EurekaLog's event handlers will be called from a background thread. You need to use some sort of synchronization if you are accessing global data in your EurekaLog's event handlers. This also means that several threads can process multiple exceptions simultaneously at the same time. You can avoid this by marshaling processing to main thread. For example, you can use TThread(Ex) and analyze .FatalException property in your main thread. See below for examples. Alternatively, you may use "Consecutive processing" option.
Both BeginThreadEx function and TThreadEx class offers two additional arguments:
Note: the EurekaLog's state will be ignored if you compile your application without EurekaLog (or with disabled EurekaLog). On the other hand, the thread name is never ignored.
Thread name is arbitrary text string which can contain any combination of characters. Thread name will be shown in debugger (Threads window) and it will be used as thread caption in bug reports. You can use thread name to identificate threads.
Quick example
type // ... your code ...
Detailed answerTThreadEx class is descendant from TThread class - thus, all 5 exception handling methods for TThread class is also applicable to TThreadEx class. For example, you can do this:
type // 1. Name the thread for easy identification in debugger and bug reports // Wait for thread's completion. // E.g. you can assign OnTerminate handler; // or you can PostMessage from thread to main thread. // You should do this only after the thread has finished.
// Clear the FatalException property, // so it won't be deleted when thread is deleted PPointer(@Thread.FatalException)^ := nil;
// Re-raise thread's exception if Assigned(E) then if Thread.ReturnValue <> 0 then
// Success // Do something with thread here... // ...
finally
This code sample works exactly as the previous code sample. You can pass thread name right into TThreadEx's constructor. Thread will be automatically named - regardless of EurekaLog's state.
However, threads launched with TThreadEx class will be EurekaLog-enabled by default, so there is no need to call the NameThread and the SetEurekaLogStateInThread functions as in example for TThread class:
procedure TMyThread.Execute; // ... your code ... You can supply an optional Boolean argument for TThreadEx's constructor to disable EurekaLog in thread, for example:
Thread := TMyThread.Create('Thread Name', False { disable EurekaLog in the thread } );
Of course, you can use the same approach while supplying the Suspended argument, for example:
Thread := TMyThread.Create( False { create thread running }, 'Thread Name', False { disable EurekaLog in the thread } );
Thread := TMyThread.Create( True { create thread suspended }, 'Thread Name', True { enable EurekaLog in the thread } );
TThreadEx class also supports anonymous threads:
procedure TForm1.Button1Click(Sender: TObject);
Since creating OnTerminate handler just for handling exceptions in thread is a lot of work - TThreadEx class presents a new property to handle exceptions automatically:
type // ... your code ...
This sample code will automatically invoke HandleException routine for FatalException property of your thread. AutoHandleException property is also available for anonymous threads created with TThreadEx class:
procedure TForm1.Button1Click(Sender: TObject);
Notes:
See also:
|