Wait Thread Finish to continue code - Delphi

Asked

Viewed 623 times

2

I need to wait for select and fill the list to finish in Thread for Function Result to receive the list loaded in the asynchronous method, is it possible? Follow the code of Function:

function PreencheCampos(const uniQuery: TuniQuery) : TList<iEstoqueLote>;
var
  lista : TList<iEstoqueLote>;
begin
  try
    Application.CreateForm(TFrmLoading, FrmLoading);
    FrmLoading.Show;

    lista := TList<iEstoqueLote>.Create;

    ThreadSql := TThread.CreateAnonymousThread(procedure
    begin
      uniQuery.Open;

      if not uniQuery.IsEmpty then
        begin
          while not uniQuery.Eof do
            begin
              aEstoqueLote := TEstoqueLote.Create;
              lista.Add(aEstoqueLote);

              if UniQuery.FindField('idestoquelote') <> nil then
                lista.Items[lista.Count - 1].idestoquelote := UniQuery.FieldByName('idestoquelote').AsInteger;

              if UniQuery.FindField('idestoque') <> nil then
                lista.Items[lista.Count - 1].idestoque := UniQuery.FieldByName('idestoque').AsInteger;

              if UniQuery.FindField('idproduto') <> nil then
                lista.Items[lista.Count - 1].idproduto := UniQuery.FieldByName('idproduto').AsInteger;

              if UniQuery.FindField('idwmsmovimentoitem') <> nil then
                lista.Items[lista.Count - 1].idwmsmovimentoitem := UniQuery.FieldByName('idwmsmovimentoitem').AsInteger;

              if UniQuery.FindField('idwmsunidadearmazenagem') <> nil then
                lista.Items[lista.Count - 1].idwmsunidadearmazenagem := UniQuery.FieldByName('idwmsunidadearmazenagem').AsInteger;

              if UniQuery.FindField('ddatavalidade') <> nil then
                lista.Items[lista.Count - 1].ddatavalidade := UniQuery.FieldByName('ddatavalidade').AsDateTime;

              if UniQuery.FindField('ddatafabricacao') <> nil then
                lista.Items[lista.Count - 1].ddatafabricacao := UniQuery.FieldByName('ddatafabricacao').AsDateTime;

              if UniQuery.FindField('nquantidade') <> nil then
                lista.Items[lista.Count - 1].nquantidade := UniQuery.FieldByName('nquantidade').AsExtended;

              if UniQuery.FindField('npesoliquido') <> nil then
                lista.Items[lista.Count - 1].npesoliquido := UniQuery.FieldByName('npesoliquido').AsExtended;

              if UniQuery.FindField('npesobruto') <> nil then
                lista.Items[lista.Count - 1].npesobruto := UniQuery.FieldByName('npesobruto').AsExtended;

              if UniQuery.FindField('nvolume') <> nil then
                lista.Items[lista.Count - 1].nvolume := UniQuery.FieldByName('nvolume').AsExtended;

              if UniQuery.FindField('ssituacao') <> nil then
                lista.Items[lista.Count - 1].ssituacao := UniQuery.FieldByName('ssituacao').AsString;

              uniQuery.Next;
            end;
        end;

      ThreadSql.Synchronize(nil, procedure
      begin
        FrmLoading.Release;
        FreeAndNil(FrmLoading);
      end);
    end);

    ThreadSql.Start;

    Result := lista;

  except on e: exception do
    begin
      TFrmTipoAviso.Mensagem('Tabela EstoqueLote : '+MensagemErroBanco(E.Message),'E',[mb_OK]);
    end;
  end;
end;
  • How do you feel about using mutex or semaphore?

  • @Leonardogetulio, are third party components for Delphi?

  • No, no. They’re all built-in. I’ll send you some links.

3 answers

1


When one creates ThreadSql of the kind CreateAnonymousThread and from a start, they will be executed immediately, however, the Result will be triggered immediately also, ie, the cursor will scroll without waiting to ThreadSql break up.

For this, try something like:

ThreadSql.Start;
...
while not ThreadSql.Finished do
  Application.ProcessMessages;

I mean, while she’s busy, just stand there and wait.

0

Follow below mutex codes and traffic lights.

The Mutex creates a single lock in memory that can be validated even by other non-Delphi applications. Some advantages are simple implementation and verification even by another application, and has the disadvantage of allowing only 1 executor at a time.

The Traffic light MREW in turn validates permission via local or global object/variable. The advantages of using MREW is that you can have numerous threads running read operations without lock on the target, the lock only happens when a thread opens with write permission, is type the database manager, when one is writing no one else can access until it is finished, when the writer releases the rest can access simultaneously. The biggest drawback is the "a little" (almost nothing) costly implementation.

Link and example mutex: http://www.planetadelphi.com.br/dica/7251/mutex---nao-deixar-que-sua-aplicacao-seja-executada-mais-do-que-uma-vez.-

program Cobrancas;

uses
Forms,
Controls,
Windows,

{$R *.res}

var
hMutex: THandle;

begin
hMutex := CreateMutex(nil, true, PChar('[{23B1EEFF-4775-4FA9-9C5-6BFEAC48F551}]'));
if (hMutex <> 0) and (GetLastError = 0) then
begin
Application.Initialize;
Application.CreateForm(TfrmPrincipal, frmPrincipal);
Application.Run;
end
else
MensagemDeAvisoH('Já Existe Uma Instância do Aplicativo Rodando...');
end.

Example semaforo MREW (multi-read exclusive-write Synchronizer):

//variável global
var
    SemaforoMREW: TMultiReadExclusiveWriteSynchronizer;

//inicializador
begin
    SemaforoMREW := TMultiReadExclusiveWriteSynchronizer.Create;
end;


//thread para leitura
begin
    SemaforoMREW.BeginRead;
    try
        //... operações de leitura
    finally
        SemaforoMREW.EndRead;
    end;
end;

//thread para escrita
begin
    SemaforoMREW.BeginWrite;
    try
        //... operações de escrita
    finally
        SemaforoMREW.EndWrite;
    end;
end;

0

You could also call a method to deal with the end of the load there before the form.release, within the syncronize zone. It turned out to be a callback notifying the end of the thread and even more performant because no loops were needed waiting for the thread to end

Browser other questions tagged

You are not signed in. Login or sign up in order to post.