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:
A most simple way to enable EurekaLog in thread manually is to use BeginThreadEx/TThreadEx:
Both routines are from EBase unit.
Important note: never use CreateThread function. Use BeginThread/BeginThreadEx function instead.
See the above links for more details about this recommended approach.
If you can not use BeginThreadEx/TThreadEx in your code (e.g. you do not create threads - think of thread pools as example), then you have to manually enable EurekaLog for your threads, for example:
function ThreadFunc(Parameter: Pointer): Integer; // Both routines are from EBase unit - // thus both can be used in the application without EurekaLog
// 1. Name thread for easy identification in debugger and bug reports // ... your normal code for the thread ...
Notice first actions in the thread: setting thread name (description) and enabling EurekaLog for this thread. This template is a recommended code template. Each of your EurekaLog-enabled threads should start with these two actions. Here is the same example for TThread class:
type // Service calls first: NameThread('This is my thread ' + ClassName); SetEurekaLogStateInThread(0, True); // ...
// Wait for the thread to complete Thread.WaitFor; // so it won't be deleted when thread is deleted PPointer(@Thread.FatalException)^ := nil; // Re-raise thread's exception if Assigned(E) then
// What if there is no exception, but thread failed? if Thread.ReturnValue <> 0 then
// Success // Do something with thread here... // ...
...and for anonymous threads:
type // ...
procedure TForm1.HandleThreadException(Sender: TObject);
...and a very similar code may be applied to any multi-threading framework that you may use: just insert calls to NameThread + SetEurekaLogStateInThread before your actual thread code.
Since a single thread may serve multiple tasks in a thread pool - it is recommended to clean after yourself:
function MyTask(lpThreadParameter: Pointer): Integer; stdcall; Win32Check(QueueUserWorkItem(MyTask, nil, 0));
This sample code enables EurekaLog (and sets thread name) only for the duration of our task. When our task is completed, thread will be released into thread pool - so we disable EurekaLog (because we don't know which task will use this thread in the next time).
See also:
|