Thread containing database connection components throws exception when they are released from memory

3

I needed to add some threads to perform certain processes in the background. This thread accesses the methods of a WebService and also performs operations on the database.

I create all the objects I need to use in this thread within itself to avoid concurrent access with components outside of it. As IBDatabase and IBTransaction (use IBX components).

So my thread looks something like this:

TThreadAtualizarDados = class(TThread)
private
  FIBDatabase: TIBDatabase;
  FIBTransaction: TIBTransaction;      
public
  constructor Create(AIBDatabase: TIBDatabase); reintroduce;
  destructor Destroy; override;
  procedure Execute; override;    
end;

As I said, everything I need to use in the thread I instantiate in itself.

constructor TThreadAtualizarDados.Create(AIBDatabase: TIBDatabase);
begin
  inherited Create(false);
  FreeOnTerminate := true;

  // conexão com o banco de dados
  FIBDatabase := TIBDatabase.Create(nil);
  FIBDatabase.LoginPrompt := false;
  FIBDatabase.DatabaseName := AIBDatabase.DatabaseName;
  FIBDatabase.Params.Text := AIBDatabase.Params.Text;

  // controle transacional
  FIBTransaction := TIBTransaction.Create(nil);
  FIBTransaction.DefaultDatabase := FIBDatabase;

  FIBDatabase.DefaultTransaction := FIBTransaction;
end;

The processes I want it to perform are successful until the execution is complete.

destructor TThreadAtualizarDados.Destroy;
begin
  inherited;
  if FIBTransaction.Active then
    FIBTransaction.Commit;

  // Comentados porque está causando erro
  //
  // FIBDatabase.Free;  
  // FIBTransaction.Free;
end;

The lines that terminate the connection and the transaction are commented out because if they are executed, a certain time after the thread termination (output of the Destroy method) is generated an error.

Error Message:

  

Program.exe faulted with message: 'application-defined exception (code 0xc000041d) at 0x77071a91'.

What does not feature Access Violation .

What might be causing this error, and what to do to solve it?

Adding More Information:

The thread is instantiated this way:

procedure TFrmAtualizaDados.p_Iniciar_Atualizacao;
begin
  TThreadAtualizarDados.Create(Dm.IdbIntsys);
end;

That is, no external processing is done on the thread. I'm not passing her reference to any variable so that I could be finalizing it manually, or anything else. Since I set the parameter of it to execute as soon as I instantiated inherited Create(false); and had it destroy itself automatically after finishing its method Execute , with FreeOnTerminate := true; , then just instantiate passing the parameters and let it work.

In addition, I have even other classes in the thread that instantiate, such as TStringList and TList , which do not give problems, only the instances of the database components generate problems if they are released from memory ( .Free ). / p>

Another detail is that the error message is triggered only when I switch from the application to Delphi in debug mode.

Of course, the " Stop on Delphi Exceptions " option in Debuger Options "is enabled .

    
asked by anonymous 06.10.2014 / 18:59

2 answers

2

Sometimes, objects that inherit from TComponent have strange behavior if they are destroyed within Threads.

To solve this type of problem, create a method to destroy objects:

procedure TThreadAtualizaDados.DestruirObjetos;
begin
  FIBDatabase.Free;  
  FIBTransaction.Free;
end;

And in the Destroy of the thread destroy them with Synchronize()

destructor TThreadAtualizarDados.Destroy;
begin
  inherited;
  if FIBTransaction.Active then
    FIBTransaction.Commit;

  Synchronize(DestruirObjetos);
end;
    
08.10.2014 / 19:15
2

As reported by Tiago Silva, if instantiated, objects IB ****, within the scope of the Execute method the problem does not occur. The logical explanation for this is that components need to be created and destroyed within the same Thread . Since the Create method runs on the Main Thread, and most likely the threads are with FreeOnTerminate := True and thus destructor is executed on the Thread created by the TThread object, then the problem occurred. / p>     

15.10.2014 / 14:29