Error filling Listview in a thread (Delphi)

Asked

Viewed 379 times

1

In a mobile project I have a code snippet that fills a Listview with data from a Dataset (I’m not using Livebindings). Up to a certain point everything was working fine until I decided to add an animation while loading the list and put the loading section inside a thread as shown below. The fact is that the load has become unstable because at some times it runs normal and at others it partially executes and the debug returns the error "Raised Exception class Segmentation fault (11)". Here is the code:

procedure TViewPesquisaCliente.PreencherListaClientes;
var
  oItem: TListViewItem;
  oId, oCodigo, oNome, oCPF: TListItemText;
  oClientes: TDataSet;
begin
  TLoading.Show(ViewPesquisaCliente, 'Carregando lista de clientes...');

  TThread.CreateAnonymousThread(
  procedure
  begin
    try
      oClientes := TControllerCliente.New.Clientes;
      lstLista.Items.Clear;
      lstLista.BeginUpdate;
      oClientes.Open;

      while not oClientes.Eof do
      begin
        oItem := lstLista.Items.Add;
        oId := TListItemText(oItem.Objects.FindDrawable('Id'));
        oCodigo := TListItemText(oItem.Objects.FindDrawable('Codigo'));
        oNome := TListItemText(oItem.Objects.FindDrawable('Nome'));
        oCPF := TListItemText(oItem.Objects.FindDrawable('CPF'));
        oId.Text := oClientes.FieldByName('Id').AsString;
        oCodigo.Text := oClientes.FieldByName('Codigo').AsString;
        oNome.Text := oClientes.FieldByName('Nome').AsString;
        oCPF.Text := oClientes.FieldByName('CPF').AsString;
        oClientes.Next;
      end;
    finally
      TThread.Synchronize(nil,
      procedure
      begin
        TLoading.Hide;
      end);

      lstLista.EndUpdate;
      oClientes.Close;
      oClientes.DisposeOf;
    end;
  end
  ).Start;
end;

The Tloading.Show section loads the animation from the screen before starting the list and Tloading.Hide closes the animation. I have no experience with threads and according to some research I read the problem may be in trying to manipulate the screen objects within the thread. I even commented the excerpt from the line "oId.Text := " to "oCPF.Text := " and it’s working again, but Listview is empty, so I have this problem. Someone would have a suggestion?

  • When I did a loading... I used the timer find it easier.

1 answer

0


You should not manipulate visual objects within a thread, let alone in mobile. Any part that involves a visual component must be inside the Synchronize or a Queue, to be guaranteed to run in the main thread.

In this case I would suggest that you try a Synchronize at the beginning (as you have in Finally) for the items.clear and beginupdate of the list, and include lstLista.Endupdate; within the last Synchronize.

I also advise to see the Queue that can be a good alternative because it does not lock the thread waiting for the main thread to do the desired code.

  • At first I managed to solve the problem by giving a Visible := False before starting the Listview update and a Visible := True after leaving the thread, but I know it is not a "stylish" solution. I will study this approach of yours and try to apply it to my code. Thank you.

  • Unconventional :D but if it worked already is not bad :D

Browser other questions tagged

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