PDA

Ver la Versión Completa : exception al llenar listview en anonymousthread


(MAJ)
10-07-2020, 05:21:31
Buenas a todos. estoy teniendo un problema al un listview en un anonymousthread el thread en android(fmx) ejecuta una consulta rest, y el resultado lo quiero cargar en un listbox con un ciclo for, pero el listbox, despues de cargarlo me da una excepcion access violation, intente poner la creacion de los items en threadsynchronize, intente poner el for dentro del synchronize pero en todos me da un acessviolation, si alguien pudiera ayudarme le agradeceria




for s in LDirs do

tthread.Synchronize(nil,
procedure
var
s:string;
begin
lboxDirectorio.BeginUpdate;
lboxDirectorio.Items.Add(TPath.GetFileName(s) + CONST_X);
lboxDirectorio.EndUpdate;
application.ProcessMessages;
end);

mas o menos ese es el codigo que utilizo para llenar el listview

bucanero
10-07-2020, 10:38:26
hola a todos

en tu código veo varios cosas que te pueden dar erroes:
-pones el BeginUpdate / EndUpdate dentro del hilo y dentro del bucle, por lo que se repite en cada ciclo, cuando solo es necesario hacerlo una vez al principio y al final del proceso.
-Por otra parte, haces un application.ProcessMessages también dentro del hilo... si ya tienes un hilo secundario, el processMessages no es necesario, y de hacerlo hazlo en el hilo principal.

A mi este código me funciona bien:

procedure TForm2.ShowFiles(LDirs: TStringDynArray);
begin
// Se pone el listBox en modo Update fuera del hilo
lboxDirectorio.Items.BeginUpdate;
// Se crea el hilo de proceso
with TThread.CreateAnonymousThread(
procedure
var
s: string;
begin
//...
for s in LDirs do
lboxDirectorio.Items.Add(TPath.GetFileName(s) + CONST_X);
//...
end) do begin
//se marca para que termine de forma automatica
freeOnTerminate := true;
//se asigna el proceso que tiene que hacer cuando termine
OnTerminate := ThreadTerminate;
// se inicia el hilo
start;
end;
end;

procedure TForm2.ThreadTerminate(sender: TObject);
begin
// al finalizaz el hilo se pone el listBox en modo normal
lboxDirectorio.Items.EndUpdate;
SetLength(Files, 0);
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
files := TDirectory.GetFiles('c:\a');
ShowFiles(files);
end;

En este ejemplo en particular no utilizo tthread.Synchronize, a pesar de ser lo recomendable para actualizar un componente visual, pero en este ejemplo en particular solo escribe un único hilo de forma secuencial y no debe de dar problemas. En caso de usar varios hilos para actualizar el componente entonces si es ya necesario.

Neftali [Germán.Estévez]
13-07-2020, 09:21:04
El Synchronize es obligatorio a utilizar en todos los Threads en el momento que acceder a un elemento que no sea "thread-safe", como son los componentes de la VCL.
Independientemente de si tú creas varios hilos o sólo uno, porque aunque tú sólo crees uno, hay otro que siempre está funcionando, que es el "Main thread" (el principal de la aplicación). Por lo tanto. debería utilizarse siempre.


En este ejemplo en particular no utilizo tthread.Synchronize, a pesar de ser lo recomendable para actualizar un componente visual, pero en este ejemplo en particular solo escribe un único hilo de forma secuencial y no debe de dar problemas. En caso de usar varios hilos para actualizar el componente entonces si es ya necesario.

Neftali [Germán.Estévez]
13-07-2020, 09:36:12
...mas o menos ese es el codigo que utilizo para llenar el listview


Dos cosas:

Yo haría una prueba sencilla para descartar, utilizando un thread "normal" (que no sea anónimo). Debería funcionar igual, pero para descartar algun problema con eso.
Comentas en tu mensaje, que el código "...más o menos es este". Yo no lo veo problema a este mensaje, pero si tu código no es exactamente este, tal vez no estemos viendo lo que te está dando problemas.

(MAJ)
26-08-2020, 21:50:24
;537947']Dos cosas:
Yo haría una prueba sencilla para descartar, utilizando un thread "normal" (que no sea anónimo). Debería funcionar igual, pero para descartar algun problema con eso.
Comentas en tu mensaje, que el código "...más o menos es este". Yo no lo veo problema a este mensaje, pero si tu código no es exactamente este, tal vez no estemos viendo lo que te está dando problemas.
en un thread normal es lo mismo, y es "mas o menos", porque en el codigo que utilizo, tengo otras variables y procedimientos que no van al caso