Raise exception in another thread

How to create an exception in another thread in Delphi? I have thread 1 and thread 2, and I want to throw an exception in thread 1 and catch it in thread 2.

EDIT

Now I see that my initial explanation is confusing. What I want to do is to INITIATE raising an exception in thread 2 from thread 1. Thus, the exception is thrown and gets into thread 2, but this process is controlled from thread 1. Let's say that I have a main thread that creates a worker flow. I need a mechanism to terminate the workflow from the main thread gracefully, but for some reasons that are irrelevant here, I cannot use the TThread.Terminate / Terminated template. Therefore, I thought that if I could initiate (inject?), Except that I lifted the work flow from the main thread, then this could be used as a stop signal.

+5
source share
6 answers

Here's a sample code snippet that throws an exception to another thread. It uses SuspendThreadto stop the stream, GetThreadContextto read the registers of the threads, changes EIP(instruction pointer), uses SetThreadContext, and then ResumeThreadto restart the stream. He works!

Unit UKilThread

Well packaged for reuse, which provides the procedure AbortThread():

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.

Renouncement

, , , . Terminate - Terminated (.. ), TerminateThread(). .NET Thread.Abort(). , .NET, , :

  • , EAbort - . . , EAbort .
  • . finally . try-finally, , , , .
  • , EnterCriticalSection try-finally, . MSDN EnterCriticalSection : "If a thread terminates while it has ownership of a critical section, the state of the critical section is undefined.". , , "", , , , .
+3
+4

, , , , . , , . .

Terminated, , Terminated. , . , .

, Terminated .

+3

, Delphi . , ( ). , .


@Max: ( Synchronize Queue), , , () .

, A , B, B , , B , .

+2

, , @David: errorState . , ( , ) ..

thread.onTerminate( ) , , frontEnd/User, , .

0

Make all your threads "messages" process the threads and don't get the "process" message, just create a message like the exception that should be passed to any other threads / main thread you need to know. I use this architecture in a distributed multi-threaded application infrastructure here .

0
source

All Articles