Closed arvanus closed 1 year ago
This is an interesting problem, but fortunately the root cause is not in the FB4D code. To my knowledge, it is a problem of the TThread
class that is not yet known. See this situation:
program testcase;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
classes,
System.Threading;
type
TMyClass = class
procedure OnTerminate(Sender: TObject);
end;
procedure run;
var
MyThread: TThread;
MyClass: TMyClass;
begin
MyClass := TMyClass.Create;
MyThread := TThread.Create(true);
MyThread.OnTerminate := MyClass.OnTerminate;
writeln('almost');
MyThread.Free;
writeln('there');
end;
{ TMyClass }
procedure TMyClass.OnTerminate(Sender: TObject);
begin
writeln('OnTerminate');
end;
begin
writeln('OK:');
run;
writeln('NOT OK:');
TTask.Create(run).start;//here is the problem
readln;
end.
TThread is hanging within TThread.ShutdownThread
when attaching an OnTerminate method.
We should report this as RSP to Embarcadero in the Quality Central.
Do you have access to Quality Central and can you do this for me with this example and name the RSP here? I would then vote for the new RSP.
In FB4D I see in this situation no possibility to solve the problem without memory leak with a workaround.
Keep in mention for further Development. Inside a thread you should use always the synchronous methods because the Synchronize Call in the asynchronous methods are not working between two back ground threads. But this is here not the root case. I just want give you a hint for the next steps.
-->FWIW I prefer to use the Omni Thread Library by Primož Gabrijelčič. For my threading requirements. Its an absolute masterpiece and highly recommended. Not sure if it suffers from the same TThread problem cited below.
Created https://quality.embarcadero.com/browse/RSP-39975 Thanks!
Just to reference a solution directly here, you need to lock the main thread in another way, l like this:
program testcase;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
classes,
System.Threading;
type
TMyClass = class
procedure OnTerminate(Sender: TObject);
end;
procedure run;
var
MyThread: TThread;
MyClass: TMyClass;
begin
MyClass := TMyClass.Create;
MyThread := TThread.Create(true);
MyThread.OnTerminate := MyClass.OnTerminate;
writeln('almost');
MyThread.Free;
writeln('there');
end;
procedure run2;
begin
readln;
end;
{ TMyClass }
procedure TMyClass.OnTerminate(Sender: TObject);
begin
writeln('OnTerminate');
end;
begin
writeln('OK:');
run;
writeln('NOT OK:');
TTask.Create(run).start;//here is the problem, MyThread.Free takes forever
// readln; //hang
TTask.Create(run2).start; //don't hang!
end.
BuildVersion = 493 Delphi 11.2
I'm using FB4D inside a rest server managed by Horse framework where each call will use a specific Firebase Firestore. My sample code works fine in the main thread, but when I run in another thread I can't release the IFirestoreDatabase reference. Here is a simple code that simulates the server:
Expected behavior I believe I could release the fDatabase object when runing everything inside a thread
Thank you for this great project and help!