Raise exception in another thread - delphi

How do I raise an exception in another thread in Delphi?
I have thread 1 and thread 2 and I want to raise an exception in thread 1 and to catch it in thread 2.
EDIT
I can see now that my initial explanation is confusing. What I want to do is to INITIATE an exception raising in thread 2 from thread 1. So exception is raised and caught in thread 2, but this process is controlled from thread 1.
Let's say that I have a main thread which creates a worker thread. I need a mechanism to stop the worker thread from the main thread gracefully, but because of some reasons, which are irrelevant here I cannot use TThread.Terminate/Terminated pattern. So I thought that if I could initiate (inject?) an exceptin raising in the worker thread from the main thread, then that could be used as a stopping signal.

You can inspire from Rob's answer here Delphi thread exception mechanism or from this Embarcadero article.

Here's a sample piece of code that raises an exception into an other thread. It uses SuspendThread to stop the thread, GetThreadContext to read the thread's registers, alters EIP (the instruction pointer), uses SetThreadContext and then ResumeThread to restart the thread. It works!
UKilThread unit
Nicely packaged for reuse unit that provides the AbortThread() routine:
unit UKillThread;
interface
uses Classes, Windows, SysUtils;
procedure AbortThread(const Th: TThread);
implementation
// Exception to be raized on thread abort.
type EThreadAbort = class(EAbort);
// Procedure to raize the exception. Needs to be a simple, parameterless procedure
// to simplify pointing the thread to this routine.
procedure RaizeThreadAbort;
begin
raise EThreadAbort.Create('Thread was aborted using AbortThread()');
end;
procedure AbortThread(const Th: TThread);
const AlignAt = SizeOf(DWORD); // Undocumented; Apparently the memory used for _CONTEXT needs to be aligned on DWORD boundary
var Block:array[0..SizeOf(_CONTEXT)+512] of Byte; // The _CONTEXT structure is probably larger then what Delphi thinks it should be. Unless I provide enough padding space, GetThreadContext fails
ThContext: PContext;
begin
SuspendThread(Th.Handle);
ZeroMemory(#Block, SizeOf(Block));
ThContext := PContext(((Integer(#Block) + AlignAt - 1) div AlignAt) * AlignAt);
ThContext.ContextFlags := CONTEXT_FULL;
if not GetThreadContext(Th.Handle, ThContext^) then
RaiseLastOSError;
ThContext.Eip := Cardinal(#RaizeThreadAbort); // Change EIP so we can redirect the thread to our error-raizing routine
SetThreadContext(Th.Handle, ThContext^);
ResumeThread(Th.Handle);
end;
end.
Demo project
Here's how to use AbortThread:
program Project23;
{$APPTYPE CONSOLE}
uses
SysUtils,
Classes,
Windows,
UKillThread;
var Th: TThread;
type
TTestThread = class(TThread)
public
procedure Execute;override;
end;
{ TTestTrehad }
procedure TTestThread.Execute;
var N: Integer;
begin
try
N := 1;
while not Terminated do
begin
WriteLn(N);
Inc(N);
Sleep(1000);
end;
except on E:Exception do
WriteLn(E.ClassName + ' / ' + E.Message);
end;
end;
begin
Th := TTestThread.Create(False);
WriteLn('Press ENTER to raize exception in Thread');
ReadLn;
AbortThread(Th);
WriteLn('Press ENTER to exit');
ReadLn;
end.
Disclaimer
Please make sure you understand what this code does before you actually use it. This is by no means a replacement for proper Terminate - Terminated logic (that is, cooperative thread shut-down), but it's a better alternative to TerminateThread(). This has been modeled after the .NET Thread.Abort() method. I have no idea how the actual .NET method was implemented but none the less read up on that because the potential problems of using this code are similar:
The method doesn't actually terminate the thread, it raises an EAbort -derived exception in the context of the thread. The thread's code might catch the exception. That's very unlikely because EAbort exceptions are not supposed to be handled.
The method might stop the thread at any time. It might stop the thread while it's handling a finally section or while setting up a new exception frame. Even if your thread uses proper try-finally blocks, it might cause memory or resource leaks if the exception is raised after a resource has been allocated but before the resource has been assigned to a variable.
The code might cause deadlocks if the thread is interrupted immediately after EnterCriticalSection and just before the try-finally that normally follows. The MSDN page for EnterCriticalSection mentions: "If a thread terminates while it has ownership of a critical section, the state of the critical section is undefined.". This came as a surprise to me, I'd intuitively expect the critical section to be "released" when the owning thread terminates, but apparently that's not so.

The way to signal your thread to cancel is to arrange for your thread to check the status of a boolean flag and respond to that. The flag is set by the controlling thread and then the worker thread does what is needed to abort. You must check the status of the flag regularly.
Such a solution would be a re-implementation of the built-in Terminated method, but you state that you can't use Terminated. I think this leaves you in a bind. Threads can't safely and reliably be terminated by force so you need a co-operative method.
I strongly advise you to re-work your architecture so that use of Terminated is viable.

That is impossible, and Delphi does not matter. Exception information reside in stack, and stack belongs to thread (each thread has its own stack). Consequently you must raise and handle exception in the same thread.
#Max: if you execute a code in a different thread (using Synchronize or Queue methods) then the exception raised by the code can only be caught in the same (different) thread.
It is possible that a thread A raises & catches the exception, passes the exception object to a thread B and the thread B re-raises the exception, but it is absolutely impossible for a thread B to catch the exception raised by thread A because each thread has its own stack.

Extending and perhaps simplifying #David's answer: I add public error message and errorState properties to my thread class. If an exception occurs in the thread, I handle or eat it (depending on what's appropriate) and set the error properties with the exception info etc.
The Main thread checks the thread class error properties in the thread.onTerminate event (which runs in main thread) and notifies frontEnd/User if necessary, showing exception exception info returned from the thread.
HTH

Make all your threads "message" processing threads, and have the failure to "process" a message just generate an exception-like message to be passed onto any other threads/main thread that need to know. I use this architecture in my distributed multi-threaded application framework here.

Related

Accessing TObject instance when it is locked by TMonitor.Enter in the calling thread

What will happen if a thread tries to access the same object locked by another thread? I know it can be handled by TMonitor.Wait(), but what if there is no handling codes to check if it is locked? Will there be an error?
In the example below, Thread1Process locks the object and Thread2Process attempts to assign a value to the object's property. Will the Thread2Process automatically wait before Thread1Process releases the lock to execute the next line var x: Integer := 1; or will it stop and throw an exception?
procedure Thread1Process(const AObject: TObjectDescendant);
begin
TMonitor.Enter(AObject);
try
// lengthy process here...
finally
TMonitor.Exit(AObject);
end;
end;
procedure Thread2Process(const AObject: TObjectDescendant);
begin
AObject.StringProperty := 'Any value';
var x: Integer := 1;
end;
We are using Delphi 11 Alexandria.
TMonitor is just a synchronization lock, nothing more. Much like TMutex, TSemaphore, etc.
It doesn't do anything to the object itself. If one thread decides to enter the lock, and a second thread doesn't, the second thread will not be blocked in any way, and no exception will be raised 1, but there is no guarantee to the stability of the object or its members. Race conditions occur due to lack of proper synchronization by all involved threads cooperating with each other.
1: unless the object itself decides to raise an exception, or a system exception is raised, like from accessing invalid memory, etc.
On a side note, your call to TMonitor.Enter() needs to be outside the try block, eg:
procedure Thread1Process(const AObject: TObjectDescendant);
begin
TMonitor.Enter(AObject);
try
// lengthy process here...
finally
TMonitor.Exit(AObject);
end;
end;

Which is the proper way to terminate a delphi application?

I would like to terminate a Delphi application without executing any other code line and I'm wondering about which is the proper way to do this. Furthermore, I would like to know if there's something wrong in what I'm actually doing at the moment.
Basically, my code looks like this:
//Freeing all objects (Obj1.Free, etc..)
Application.Terminate;
Halt;
Is this the right way to stop a Delphi application or should it be done in another way?
Application.Terminate() breaks the message loops in TApplication.Run() and TForm.ShowModal(), allowing the main thread to exit normally, perform necessary cleanups, etc.
Vcl.Forms.TApplication.Terminate
Ends application execution.
Call Terminate to end the application programmatically. By calling Terminate rather than freeing the application object, you allow the application to shut down in an orderly fashion.
Terminate calls the Windows API PostQuitMessage function to perform an orderly shutdown of the application. Terminate is not immediate.
Terminate is called automatically on a WM_QUIT message and when the main form closes.
Halt(), on the other hand, is an immediate abnormal termination. Basically, ripping the process out of memory. Use it only in extreme situations where no other option is available.
System.Halt
Initiates the abnormal termination of a program.
Halt performs an abnormal termination of a program and returns to the operating system.
To perform a normal termination of a Delphi application, call the Terminate method on the global Application object. If the application does not use a unit that provides an Application object, call the Exit procedure from the main Program block.
I would like to terminate a Delphi application without executing any other code.
Neither Application.Terminate nor Halt will achieve that. The former performs an orderly termination. Lots of code will execute. Calling Halt is more hopeful. That is an abnormal termination. But unit finalization code is executed.
If you wish to exit as quickly as possible, executing the minimum amount of code along the way, call ExitProcess. That's the final step of Halt and by calling ExitProcess directly you avoid all the steps that Halt takes before it calls ExitProcess.
I had some problems with Application.Terminate, because I had to start the Form Close procedure, so I did only:
Form1.Close;
I found a new solution inside .dproj
begin
ReportMemoryLeaksOnShutdown := True;
Application.Initialize;
Application.CreateForm(TFormMain, FormMain);
if Not(VerifyCode()) then
begin
ShowMessage('Software unregistered!');
Application.Terminate;
end
else
Application.Run;
end.
Just to leave a point on a extra problem if code must be on main form OnCreate.
Try such code on the Main Form OnCreate event. It does not work as expected, main form is shown, then the application is finished.
To be able to see it, add another form and put on its creation a long loop.
It seems like all the Application.CreateForm on the main project source are executed.
Sample code:
procedure TMyMainForm.FormCreate(Sender: TObject);
begin
ShowMessage('[1] This must allways be shown');
if mrOK=MessageDlg('Exit?',mtConfirmation,[mbOK,mbCancel],0)
then begin
Application.Terminate;
Exit;
end;
ShowMessage('[2] This must not allways be shown');
end;
procedure TMyOtherForm.FormCreate(Sender: TObject);
begin
ShowMessage('[3] This must not allways be shown');
end;
With that code messages [1] and [3] are allways shown.
Only way to not show [3] is to call Halt.
Note: Why such code on MainForm OnCreate? Simple answer could be, the exe checks conditions to be run and see they are not meet (missing files, etc), rude one (sorry for that), just because i want/need to.
I know this is an old thread, but would appreciate comments on this addition to the thread if anyone is still listening.
For quite some time I have called Application.Terminate followed by ExitProcess(0). My theory is that Application.Terminate does the graceful cleanup, but ExitProcess prevents any other code from executing. It seems to work, and I don't get reports of memory leaks or other ill effects. Code would be something like:
Procedure (KillTheApp);
begin
Application.Terminate;
Application.ProcessMessages;
ExitProcess(0);
end;

Thread Error: The Handle is Invalid (6) when trying to Free a suspended thread

In a given example I am receiving an exception when calling AThread.Free.
program Project44;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes, Windows;
type
TMyException = class(Exception);
var
AThread: TThread;
begin
AThread := TThread.Create(True);
try
AThread.FreeOnTerminate := True;
//I want to do some things here before starting the thread
//During the setup phase some exception might occur, this exception is for simulating purpouses
raise TMyException.Create('exception');
except
AThread.Free; //Another exception here
end;
end.
I have two questions:
How should I free AThread instance of TThread in a given example?
I don't understand, why TThread.Destroy is calling Resume before destroing itself. What is the point of this?
You can't set FreeOnTerminate to True and call Free on the thread instance. You have to do one or the other, but not both. As it stands your code destroys the thread twice. You must never destroy an object twice and of course when the destructor runs for the second time, errors occur.
What happens here is that since you created the thread suspended, nothing happens until you explicitly free the thread. When you do that the destructor resumes the thread, waits for it to complete. This then results in Free being called again because you set FreeOnTerminate to True. This second call to Free closes the handle. Then you return to the thread proc and that calls ExitThread. This fails because the thread's handle has been closed.
As Martin points out in the comment you must not create TThread directly since the TThread.Execute method is abstract. Also, you should not use Resume which is deprecated. Use Start to begin execution of a suspended thread.
Personally I don't like to use FreeOnTerminate. Using this feature results in the thread being destroyed on a different thread from which it was created. You typically use it when you want to forget about the instance reference. That then leaves you uncertain as to whether or not the thread has been destroyed when your process terminates, or even whether it is terminating and freeing itself during process termination.
If you must use FreeOnTerminate then you need to make sure that you don't call Free after having set FreeOnTerminate to True. So the obvious solution is to set FreeOnTerminate to True immediately before after calling Start and then forget about the thread instance. If you have any exceptions before you are ready to start then you can safely free the thread then since you FreeOnTerminate would still be False at that point.
Thread := TMyThread.Create(True);
Try
//initialise thread object
Except
Thread.Free;
raise;
End;
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;
A more elegant approach would be to move all the initialisation into the TMyThread constructor. Then the code would look like this:
Thread := TMyThread.Create(True);
Thread.FreeOnTerminate := True;
Thread.Start;
Thread := nil;
The situation is very complicated in your case.
First, you does not actually free a suspended thread; a thread is resumed in destructor:
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
Since Terminate is called before Resume, the Execute method never runs, and thread terminates immediately after being resumed:
try
if not Thread.Terminated then
try
Thread.Execute;
except
Thread.FFatalException := AcquireExceptionObject;
end;
finally
Result := Thread.FReturnValue;
FreeThread := Thread.FFreeOnTerminate;
Thread.DoTerminate;
Thread.FFinished := True;
SignalSyncEvent;
if FreeThread then Thread.Free;
Now look at the last line - you call destructor (Thread.Free) from destructor itself!
Fantastic bug!
To answer your questions:
You just can't use FreeOnTerminate:= True in your code;
You should ask Embarcadero why TThread is designed so; my guess - some code
(DoTerminate method) should be executed in thread context while
thread terminates.
You can send a feature request to QC: add FFreeOnTerminate:= False to TThread.Destroy implementation:
destructor TThread.Destroy;
begin
FFreeOnTerminate:= False;
// everything else is the same
..
end;
That should prevent recursive desctructor call and make your code valid.

how to get the information that did when thread is paused

how can i get actions ,i did when my thread is paused after resumed (Sorry for my bad english )
ok i will explain with code
function mythreadf(p:Pointer):DWORD stdcall;
var i:Integer;
begin
for i:=0 to 1000000 do begin
if myevent.WaitFor(INFINITE)=wrsignaled
then
begin
if Form1.RadioButton1.Checked then ShowMessage('Checked');
Form1.Label1.Caption:=IntToStr(i);
end;
end;
end;
i am pausing and resuming my thread using resetevent and setevent
after i paused my thread by clicking resetevent button and then i checked radiobotton1 after that when resume my thread by using setevent again .dont send error occuring and applications closing :(
can any one help me in this issue
regards
Edit 1:
Error image
http://i49.tinypic.com/11r7nkn.jpg
Accessing VCL UI controls directly in a worker thread is NOT thread-safe (even ShowMessage() is not thread-safe. Use the Win32 API MessageBox() directly instead). All kinds of bad things can happen, including crashes. You must delegate your UI access to the main thread instead. The TThread class has a Synchronize() method for that purpose. Or you can use any other inter-thread synchronization of your choosing, such as by using SendMessage() to send custom messages to a hidden window created in the main thread via AllocateHWnd() or CreateWindow/Ex().
Your thread, as Remy says, should not be accessing the checkbox. Also it's bad programming style. Your background thread has a purpose? That purpose will help you find a name. If you create a class that inherits from TThread, you will get farther, faster.
interface
type
TMyElephantCountingThread = class(TThread)
protected
FResultStr:String; // holds something for later display on the user interface
FOptionChecked:Boolean; // set from main thread, to tell background thread whether or not a checkbox option is checked.
....
end;
....
implementation
....
function TMyElephantCountingThread.ElephantCounterResults;
begin
// all data fields in here is local to this thread
if FOptionChecked then
FResultStr := IntToStr(FIntegerValue);
end;
As you can see my code above uses only fields that belong to my thread object.
If FOptionChecked needs to be set equal to the value of Checkbox.checked, that must be done in the main thread.
You can not copy and paste write code from your foreground thread (which can access your VCL objects) into your background thread code (which can not safely access those objects), and not expect problems.

TThread.resume is deprecated in Delphi-2010 what should be used in place?

In my multithread application
I use TThread.suspend and TThread.resume
Since moving my application to Delphi 2010 I get the following warring message
[DCC Warning] xxx.pas(277): W1000 Symbol ‘Resume’ is deprecated
If Resume is deprecated what should be used in place?
EDIT 1:
I use the Resume command to start the thread - as it is Created with 'CreateSuspended' set to True and Suspend before I terminate the thread.
EDIT 2:
Here is a link the delphi 2010 manual
Charles if do you read the code of TThread class , do you find the answer.
TThread = class
private type
..
..
..
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
procedure AfterConstruction; override;
// This function is not intended to be used for thread synchronization.
procedure Resume; deprecated;
// Use Start after creating a suspended thread.
procedure Start;
// This function is not intended to be used for thread synchronization.
procedure Suspend; deprecated;
procedure Terminate;
See this link RAD Studio 2010: Community pulse: The day after. (Part 2)
Edit:
If you need to synchronize threads, you can use a scheme based on TMutex, TEvent and critical sections.
Bye.
Use TThread.Start instead of .Resume
--EDIT--
Start can of course only be used with Delphi 2010 (and later, presumably) to start a thread that was created suspended (where you would have used Resume before).
Using Resume/Suspend (or corresponding WinAPI functions) for thread synchronisation is NOT recommended. See the discussion here (have a look at Barry Kelly's comments).
Suspend and Resume were (or used to be) potentially broken in the TThread class (if you look at the source you will see that the Suspend method directly and unconditionally sets a Boolean to indicated thread suspended state rather than more robustly deriving this state from the execution count on the thread handle. Ironically the Resume method does use this more robust indicator to update the suspended state Boolean).
This is possibly why they have been deprecated. It's also why I implemented my own class to encapsulate a Windows thread with a more robust suspend and resume mechanism as well as the ability to Restart a thread once it had completed.
I'm not sure why their deprecation is supposedly related to synchronization. Suspending and resuming threads is not necessarily related to synchronization, although I can see how it might be. It's interesting to note that the equivalent methods in the .NET framework Thread class are similarly marked as obsoleted. And the same comments w.r.t synchronization appear in the Windows API documentation for thread suspend/resume.
If using deprecated methods makes you nervous and you still wish to suspend/resume you could always use the Windows API to suspend and resume the thread by reference to it's handle.
Just in case all you wanted to do was get rid of the compiler hints
(1) To get rid of the compiler hint when Starting a Thread ...
replace
MyThread := TMyThread.Create(True);
MyThread.Resume;
with
MyThread := TMyThread.Create(True);
MyThread.Start;
(2) To get rid of the compiler hint when Stopping a Thread ...
replace
MyThread.Suspend;
MyThread.Terminate;
with
MyThread.Terminate;
Not a big deal at all. Beware of attempted obfuscation.
Thread behavior control code should lie with in a thread procedure. Use appropriate sync objects and corresponding API calls in order to suspend/resume thread execution. Doing it from outside is a dangerous practice. So there was a decision to depricate it.
Use
Suspended := False; // Resume;
or
Start;
You should create the thread as follows:
constructor TSignalThread.Create;
begin
// create event handle first!
FEventHandle := CreateEvent(
{security} nil,
{bManualReset} true,
{bInitialState} false,
{name} nil);
FWaitTime := 10;
inherited Create({CreateSuspended}false);
end;
This way a call to Start is not required.
See http://www.gerixsoft.com/blog/delphi/creating-threads for an explanation why this code works.
#mghie (a little late, I know)
take for example madexcept and alike. If your application crashes and a bug report is being shown to user, that means that the dialog waits for use input. If it so happens that the crash is a result of a thread action (not necessarily a thread crashing), if you do not suspend the threads, the screen will be filled with bug report dialogs.
example 2: logging. for any particular reason, I at least, had the need to log some threads execution state. That includes the current stack trace. Now, as you (should) know, you cannot do that while the thread is running because during the time you collect information about it, the threads keeps doing stuff so by the time you finish collection, the information collected will not be consistent. Hence, you need to suspend the thread.
And I can go on with practical examples on thread management. Granted, these are not things you do in every day programming, but at least the first example I am sure that many of you are using, even if you are not aware of the internals of it. Debuggers? again, you use them.
But indeed, in all these cases, TThread is not used, since the work is done on thread handles. So, indeed, a valid example of TThread suspend usage is hard to come by. But threads in general, that's another story.

Resources