-1

i was trying to do a little splashscreen so my program could open querys withaout blocking my aplication. The code i wrote is this.

procedure TOpenThread.OpenTable;
begin
  FActiveTable.NonBlocking := true;
  FActiveTable.open;
end;
procedure TOpenThread.AbrirTablas;
begin
    FActiveTable := FOwnerPlan.TablasEdicion.Tabla;
    Synchronize(OpenTable);
    while FActiveTable.Executing do
    begin
     if Terminated then CancelExecution;
     sleep(10);
    end;
    FActiveTable.NonBlocking := false;
end;

This code is executing in a thread, and keeps doing it while the main thread gets stucked

I'm using delphi 2007

1 Answers1

1

This code is executing in a thread

Now, it does not. Your code is:

Synchronize(OpenTable);

This explicitly means OpenTable procedure is executed within Main VCL thread and outside of your background auxillary TOpenThread.

More details on Synchronize that you may try to learn from are at https://stackoverflow.com/a/44162039/976391

All in all, there is just no simple solutions to complex problems.

If you want to offload DB interactions into a separate thread, you would have to make that thread exclusive owner and user of all DB components starting from the very DB connection and up to every transaction and every query.

Then you would have to make means to ASYNCHRONOUSLY post data requests from Main VCL Thread to the DB helper thread, and ASYNCHRONOUSLY receive data packets from it. Something like OmniThreadLibrary does with data streams - read their tutorials to get a gist of internal program structure when using multithreading.

You may TRY to modify your application to the following rules of thumb. It would not be the fastest multithreading, but maybe the easiest.

  • all database components work is exclusively done inside TOpenThread.Execute context and those components are local members variables to the TOpenThread class. The connection-disconnection made only within TOpenThread.Execute; TOpenThread.Execute waits for the commands from the main thread in the almost infinite (until the thread gets terminated) and throttled loop.

  • specific database requests are made as anonymous procedures and are added to some TThreadedQueue<T> public member of TOpenThread object. The loop inside .Execute tries to fetch the action from that queue and execute it, if any exists, or throttle (Yield()) if the queue was empty. Neither Synchronize nor Queue wrappers are allowed around database operations. Main VCL thread only posts the requests, but NEVER waits for them to be actually executed.

  • those anonymous procedures after being executed do pass the database results back into main thread. Like http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/ or like Sending data from TThread to main VCL Thread or by any other back-into-main-thread way.

  • TOpenThread.Execute only exits the loop if the Terminated flag is set and the queue is empty. If Terminated is set then immediate exit would loose the actions still waiting on queue unprocessed.

Seems boring and tedious but easy? Not at all, add there that you would have to intercept exceptions and process all the errors in the async way - and you would "loose any hope entering this realm".

PS. and last but not least, about "This code is executing in a thread, and keeps doing it while the main thread gets stucked" supposition, frankly, I guess that you are wrong here and i think that BOTH your threads are stuck by one another. Without fully understanding how thread-to-thread locking is designed to work in this specific component, carpet-bombing code with calls to Synchronize and other inter-thread locking tools, you have quite a chance to just chase them all your threads into the state of mutual lock, deadlock. See http://stackoverflow.com/questions/34512/

Arioch 'The
  • 15,799
  • 35
  • 62
  • Yes, but the "NonBlocking" property of the dataset should make it execute outside the main thread – Ismael Esteruelas Regalado May 31 '17 at 12:33
  • 1
    No, the method `OpenTable` is executed within the main thread. If not - then there is no reason to bother with creating `TOpenThread` - just call `.OpenTable` from your main thread code! The question is that some activity (but not all ! ) is no more executed within `OpenTable` but gets off-loaded to be executed by some other methods. That I do not know for sure. However what definitely is true, is that `Synchronize` is killing multithreading for its parameter, it is what that call was introduced for. – Arioch 'The May 31 '17 at 12:47