Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi : How to create and use Thread locally?

My database is in a VPS and I should get some query from my tables

Because of getting query from server taking long time ( depending on Internet speed ! ) , I want to use threads to get queries

Now I create a thread and get query and then send result to my forms with sending and handling messages

I want to know is it possible to create and use a thread locally ?!?

My mean is :

procedure Requery;
var
 ...
begin
 Create Thread;
 ...

 Pass my Query Component to Thread
 ...

 Getting Query in Thread;
 ...

 Terminate and Free Thread
 ...

 Do next jobs with Query;
 ...

end;

The main part is last part ( Do next jobs ... ) , I dont want to use query result in a message handler and I want to use them in the same procedure and after thread job

Is it possible ?!

I think this is not possible with Delphi TThread class and I should use other threading techniques ...

  • I`m using Delphi XE6
like image 394
Mahmoud_Mehri Avatar asked Sep 20 '15 12:09

Mahmoud_Mehri


1 Answers

What you describe is not the best use of a thread. The calling code is blocked until the thread is finished. That negates the use of running code in parallel at all. You could just perform the query directly instead:

procedure Requery;
var
  ...
begin
  ...
  // run query
  // do next jobs with query
  ...
end;

That being said, since you are using XE6, you can create a "local" thread by using the TThread.CreateAnonymousThread() method, specifying an anonymous procedure that "captures" the variables you want it to work with, eg:

procedure Requery;
var
  Event: TEvent;
  H: THandle;
begin
  Event := TEvent.Create;
  try
    TThread.CreateAnonymousThread(
      procedure
      begin
        try
          // run query in thread
        finally
          Event.SetEvent;
        end;
      end
    ).Start;
    H := Event.Handle;
    while MsgWaitForMultipleObjects(1, H, False, INFINITE, QS_ALLINPUT) = (WAIT_OBJECT_0+1) do
      Application.ProcessMessages;
  finally
    Event.Free;
  end;

  // Do next jobs with query
  ...
end;

Alternatively:

procedure Requery;
var
  Thread: TThread;
  H: THandle;
begin
  Thread := TThread.CreateAnonymousThread(
    procedure
    begin
      // run query in thread
    end
  );
  try
    Thread.FreeOnTerminate := False;
    H := Thread.Handle;
    Thread.Start;
    while MsgWaitForMultipleObjects(1, H, False, INFINITE, QS_ALLINPUT) = (WAIT_OBJECT_0+1) do
      Application.ProcessMessages;
  finally
    Thread.Free;
  end;

  // Do next jobs with query
  ...
end;

However, threading is more useful when you let it run in the background while you do other things and then you act when the thread has finished its work. For example:

procedure TMyForm.Requery;
var
  Thread: TThread;
begin
  Thread := TThread.CreateAnonymousThread(
    procedure
    begin
      // run query in thread
    end
  );
  Thread.OnTerminate := QueryFinished;
  Thread.Start;
end;

procedure TMyForm.QueryFinished(Sender: TObject);
begin
  if TThread(Sender).FatalException <> nil then
  begin
    // something went wrong
    Exit;
  end;
  // Do next jobs with query
end;
like image 125
Remy Lebeau Avatar answered Sep 30 '22 21:09

Remy Lebeau