user
user

Reputation: 681

Problem using Synchronize

I need to execute a function in a separated thread and wait until the thread is finished.

For example, here's the original function :

Procedure Search;
begin
  CallA;
  CallB;
end;

This is the modified function :

Procedure Search;
var
  testMyThread: TMyThread;
  Done: Boolean;
begin
  // create a new thread to execute CallA
  testMyThread:=TMyThread.Create(False,Done);
  WaitForSingleObject(testMyThread.Handle, INFINITE );
  if not Done then
  begin
    TerminateThread(testMyThread.Handle, 0);
  end
  else;  
  CallB;
end

unit uMyThread;

interface

uses classes;

type
  TMyThread = class(TThread)
  private
    { Private declarations }
    FDone: ^boolean;
  protected
    procedure Execute; override;
  public
    constructor Create(const aSuspended: boolean; var Done: boolean);
    procedure CallA;
  end;

implementation

uses uMain;

constructor TMyThread.Create(const aSuspended: boolean;
  var Done: boolean);
begin
  inherited Create(aSuspended);
  FDone := @Done;
end;

procedure TMyThread.CallA;
begin
  // enumurating several things + updating the GUI
end;

procedure TMyThread.Execute;
begin
  inherited;
  Synchronize(CallA); // << the problem
  FDone^ := true;
end;
end.

Could you tell me why the thread code above doesn't work (CallA never being executed) if I use Synchronize inside TMyThread.Execute ?

Upvotes: 4

Views: 230

Answers (2)

coding Bott
coding Bott

Reputation: 4357

the Delphi tthread class has an event called onThreadTerminate. This is called in the context of the application thread, when the thread leaves the execute method.

you can use this event in your application.

Upvotes: 1

Andrej Kirejeŭ
Andrej Kirejeŭ

Reputation: 5481

Because Synchronize will call a method within application's message loop. And using WaitForSingleObject you simply put all application on hold. Try this:

  Procedure Search;
  var
    testMyThread: TMyThread;
    Done: Boolean;
  begin
    // create a new thread to execute CallA
    testMyThread:=TMyThread.Create(False,Done);

    while (not Done) and (not Application.Terminated) do
      Application.ProcessMessages;

    if not Application.Terminated then
      CallB;
  end

Upvotes: 5

Related Questions