Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 10-02-2011
Avatar de eflosten
eflosten eflosten is offline
Miembro
 
Registrado: abr 2010
Posts: 24
Poder: 0
eflosten Va por buen camino
TIdFTP list dentro de Thread

Buenos dias delphinianos, os traigo una duda que ni San Google ni el buscador de estos foros me ha conseguido resolver.

Tengo un TThread, que alberga un IdFTP, al que llamo desde el hilo principal para hacer un List de los archivos remotos. El problema surge en que, al hacer el List, me da un error de Access Violation, el cual haciendo el mismo proceso desde el main thread no me salta, pero no consigo averiguar por qué / como solucionarlo.

Ahi va el código:

La llamada:
Código Delphi [-]
HiloFTP:=THiloFTP.CreateLista(SlVersionesDescargables,lblProgDescarga);
  HiloFTP.execute;

El create del hilo:
Código Delphi [-]
constructor THiloFTP.CreateLista(lista: TStringList; labelProceso: Tlabel);
begin
 inherited Create(false);
 Self.FTP:=TIdFTP.Create(nil);
 Self.FTP.OnWork :=FTPWork;
 Self.FTP.Username := '*****'; // Esto está con los datos reales obviamente
 Self.FTP.Password := '*****';
 Self.FTP.Host := 'ftp.mihost.es';
 Self.lblProgreso:=labelProceso;
 Self.listaArchivos:= lista;
 Self.RutaRemota:=carpeta;
 Self.modo:='LISTA';
end;

El proceso que trabaja realmente. Se le llama desde el Execute según el modo
(intento aprovechar el mismo hilo para hacer descargas en otro punto del programa, para eso el modo y el create sobreescrito)
Código Delphi [-]
procedure THiloFTP.ListarArchivos;
begin
 try
 listaArchivos.Clear;
 if lblProgreso <> nil then lblProgreso.caption:='Conectando...';
 FTP.Connect;
 if lblProgreso <> nil then lblProgreso.caption:='Conectado.';
  if lblProgreso <> nil then lblProgreso.caption:='Buscando archivos';
 FTP.List(ListaArchivos,'',false); // <-- Aqui es donde da el Access Violation
   if lblProgreso <> nil then lblProgreso.caption:='Desconectando...';
 FTP.Disconnect;
 if lblProgreso <> nil then lblProgreso.caption:='Desconectado.';
  finally
  if FTP.connected then FTP.Disconnect;
  end;
end;


Cabe destacar que es mi segundo TThread, aún estoy aprendiendo a manejarlos y es probable que tenga algo mal planteado y no me de cuenta.

Un saludo, y gracias de "hantevraso" por vuestra ayuda
Responder Con Cita
  #2  
Antiguo 10-02-2011
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 17
rgstuamigo Va por buen camino
Arrow

Segun veo el primer Parámetro del procedure List del componente FTP debería estar instanciado(osea creado) al momento de usarlo.
En tu caso es tu variable "listaArchivos"...
Mi pregunta es ¿en qué parte del código estás instanciado dicha variable? o mejor dicho la variable "lista" que le asignas a la variable "listaArchivos" en tu constructor CreateLista ¿dónde la creas? o que és?
Saludos...
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7

Última edición por rgstuamigo fecha: 10-02-2011 a las 17:11:14.
Responder Con Cita
  #3  
Antiguo 10-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
A mi me faltan un par de cosas que tienes en el Create; Hay una variable carpeta y un evento OnWork; El segundo supongo que está definido en el Thread y la primera no se de dónde sale.

¿Cómo y dónde llamas al método ListarArchivos? ¿Synchronize?
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #4  
Antiguo 10-02-2011
Avatar de eflosten
eflosten eflosten is offline
Miembro
 
Registrado: abr 2010
Posts: 24
Poder: 0
eflosten Va por buen camino
La variable Carpeta la quité por limpiarlo un poco para vosotros, la uso para un FTP.ChangeDir que ahora mismo tenía comentado, si me quedó algún resto por ahi no lo tengais en cuenta.

listaArchivos lo asigno en el Create a la lista que viene por parámetros, la cual viene inicializada desde el hilo principal (SlVersionesDescargables). Edito el primer post para quitar el Carpeta (que vendría desde el hilo principal por parámetro).

Pues no, no lo edito que ya no me deja, pero bueno, esa linea consideradla comentada.

A ListarArchivos lo llamo desde Execute:

Código Delphi [-]
procedure THiloFTP.Execute;
begin
  if modo = 'DESCARGA' then BajarArchivo
  else if modo = 'LISTA' then ListarArchivos;
end;

El OnWork en este caso no deberia afectar, pero aqui lo teneis

Código Delphi [-]
procedure THiloFTP.Sincronizar();
begin
  Barra.Position := Progreso div 1024;
  if lblProgreso <> nil then lblProgreso.Caption:=intToStr(Progreso div 1024) + ' / '+IntToStr(tamArchivo)+' KB';
end;
procedure THiloFTP.FTPWork(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Integer);
begin
  Progreso:=AWorkCount;
  Synchronize(Sincronizar);
end;

Última edición por eflosten fecha: 10-02-2011 a las 17:06:12.
Responder Con Cita
  #5  
Antiguo 10-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por eflosten Ver Mensaje
listaArchivos lo asigno en el Create a la lista que viene por parámetros, la cual viene inicializada desde el hilo principal (SlVersionesDescargables).
OK.
Entiendo que no es una variable interna al Thread, por lo tanto deberías acceder a ellas dentro de un Synchronize (creo). Otra opción es que crees una interna y al final asignes los valores.

Creo que ahí puede estar el problema.
Como bien dices, si el OnWok es interno, no debería afectar.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #6  
Antiguo 10-02-2011
Avatar de eflosten
eflosten eflosten is offline
Miembro
 
Registrado: abr 2010
Posts: 24
Poder: 0
eflosten Va por buen camino
Lo que me llama la atención es que si pongo este código en el lugar donde creo el hilo, funciona perfectamente:

Código Delphi [-]
// HiloFTP:=THiloFTP.CreateLista(SlVersionesDescargables,lblProgDescarga);// HiloFTP.execute;
 FTP:=TIdFTP.Create(nil);
  FTP.Username := '******';
  FTP.Password := '******';
  FTP.Host := '*********';

  FTP.Connect;
  FTP.List(SlVersionesDescargables,'',false);

Vamos, que es alguna historia dentro del hilo. Voy a poneros el código del TThread completo, a ver si es alguna metedura de pata que no consigo ver en la propia creación del hilo (repito que es el 2º hilo que programo, estoy muy pez aún en ese tema).

Código Delphi [-]
unit unitHiloFTP;
interface
uses IdFTP, IdBaseComponent, IdComponent, IdTCPConnection,
 IdTCPClient, IdExplicitTLSClientServerBase, Variants, Classes, messages, dialogs,StdCtrls, ComCtrls, Sysutils;
 type THiloFtp = class(TThread)
  private
    modo:string;
    Barra:TProgressBar;
    lblProgreso:TLabel;
    procedure FTPWork(ASender: TObject; AWorkMode: TWorkMode;
   AWorkCount: Integer);
    procedure BajarArchivo;
    procedure ListarArchivos;
    procedure InicializarFTP;
  protected
   procedure Sincronizar;
  public
   FTP: TIdFTP;
   listaArchivos:TStringList;
   RutaRemota: String;
   ArchOrigen,ArchDestino: string;
   tamArchivo,Progreso:integer;
      Terminated: boolean;
   constructor CreateDescarga(CarpetaRemota,ArchRemoto,ArchLocal:string;labelProceso:Tlabel;barraProceso: TProgressBar);overload;
   constructor CreateLista(lista: TStringList;carpeta:string;labelProceso:TLabel);overload;
   procedure Execute; override;
end;
implementation
constructor THiloFTP.CreateDescarga(CarpetaRemota,ArchRemoto,ArchLocal:string;labelProceso:Tlabel;barraProceso: TProgressBar);
begin
 inherited Create(False);
  Terminated := false;
 InicializarFTP;
 Barra:=barraProceso;
 RutaRemota:=carpetaRemota;
 ArchOrigen:=ArchRemoto;
 ArchDestino:=ArchLocal;
 lblProgreso:=labelProceso;
 modo:='DESCARGA';
end;
constructor THiloFTP.CreateLista(lista: TStringList;Carpeta: string;labelProceso: Tlabel);
begin
 inherited Create(false);
 Terminated := false;
 InicializarFTP;
 lblProgreso:=labelProceso;
 listaArchivos:= lista;
 RutaRemota:=carpeta;
 modo:='LISTA';
end;
Procedure THiloFTP.InicializarFTP();
begin
 FTP:=TIdFTP.Create(nil);
 FTP.OnWork :=FTPWork;
 FTP.Username := '******';
 FTP.Password := '******';
 FTP.Host := 'ftp.mihost.es';
end;
procedure THiloFTP.Sincronizar();
begin
 Barra.Position := Progreso div 1024;
 if lblProgreso <> nil then lblProgreso.Caption:=intToStr(Progreso div 1024) + ' / '+IntToStr(tamArchivo)+' KB';
end;
procedure THiloFTP.FTPWork(ASender: TObject; AWorkMode: TWorkMode;
 AWorkCount: Integer);
begin
 Progreso:=AWorkCount;
 Synchronize(Sincronizar);
end;
procedure THiloFTP.Execute;
begin
 if modo = 'DESCARGA' then BajarArchivo
 else if modo = 'LISTA' then ListarArchivos;
 Terminated:=true;
 Terminate;
end;
procedure THiloFTP.BajarArchivo;
var FS: TFileStream;
begin
 try
   if lblProgreso <> nil then lblProgreso.caption:='Abriendo archivo local...';
   FS:=TFileStream.Create(archDestino,FmOpenWrite);
   if lblProgreso <> nil then lblProgreso.caption:='Conectando...';
   FTP.Connect;
   FTP.ChangeDir(rutaRemota);
   if lblProgreso <> nil then lblProgreso.caption:='Descargando...';
   tamArchivo:=FTP.Size( ExtractFileName( archOrigen ) ) div 1024;
   FTP.Get( archOrigen, fs, False );
   if lblProgreso <> nil then lblProgreso.caption:='Desconectando...';
   FTP.Disconnect;
   if lblProgreso <> nil then lblProgreso.caption:='Desconectado.';
   fs.free;
  except
   on e: exception do Showmessage( 'No se ha podido descargar el archivo:'+#13#10+e.Message);
  end;
end;
procedure THiloFTP.ListarArchivos;
begin
 try
  listaArchivos.Clear;
  if lblProgreso <> nil then lblProgreso.caption:='Conectando...';
  FTP.Connect;
  if lblProgreso <> nil then lblProgreso.caption:='Conectado';
  //FTP.ChangeDir(rutaRemota);
  if lblProgreso <> nil then lblProgreso.caption:='Buscando archivos';
  FTP.List(ListaArchivos,'',false);
  if lblProgreso <> nil then lblProgreso.caption:='Desconectando...';
  FTP.Disconnect;
  if lblProgreso <> nil then lblProgreso.caption:='Desconectado';
 finally
  if FTP.connected then FTP.Disconnect;
    Terminated := True;
  end;
end;
end.


Edit:

Neftali, el problema no es con la variable en sí, porque puedo acceder a ella desde el hilo sin problemas, e incluso FTP.List sin parámetros tambien me falla.
Edit 2:
He probado a tratarlo directamente sobre un TSTringList local a la función, y me da el mismo error. Me llama la atención que SIEMPRE el access violation es a la misma direccion de memoria: 00000250

Última edición por eflosten fecha: 10-02-2011 a las 18:22:24.
Responder Con Cita
  #7  
Antiguo 10-02-2011
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Pues yo he probado más o menos como lo tienes y me funciona.

Un par de cosas.

(1) en la llamada no utilices Execute (porque si no lo estás lanzando en el hilo principal), debes utilizar Resume.

(2) He cambiado los parámetros del evento OnWork, porque en XE han cambiado (Integer por Int64).
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #8  
Antiguo 10-02-2011
Avatar de eflosten
eflosten eflosten is offline
Miembro
 
Registrado: abr 2010
Posts: 24
Poder: 0
eflosten Va por buen camino
Ahora que mencionas el XE, no especifiqué con qué versión estoy trabajando:

Delphi 2007 con el Indy de serie.
Puede ser algun bug del propio Indy? Por que si no no lo entiendo...

Gracias por el tip, usaré Resume a partir de ahora
Responder Con Cita
  #9  
Antiguo 14-02-2011
Avatar de eflosten
eflosten eflosten is offline
Miembro
 
Registrado: abr 2010
Posts: 24
Poder: 0
eflosten Va por buen camino
He conseguido aislar mejor el error, resulta que, aunque la exception la tira en el FTP.List, el error viene desde el constructor del modo lista.

Si hago FTP.List llamandolo desde el CreateDescarga, funciona perfecto.

Tengo mal implementado o algun error en el doble constructor para que uno funcione bien y el otro no?
Responder Con Cita
  #10  
Antiguo 14-02-2011
Avatar de eflosten
eflosten eflosten is offline
Miembro
 
Registrado: abr 2010
Posts: 24
Poder: 0
eflosten Va por buen camino
Vale, ya he localizado el error...

El proceso List del FTP hace saltar el evento OnWork, el cual en mi caso actualiza el estado de la ProgressBar Barra, la cual se asigna en CreateDescarga, pero no en CreateLista, de ahi el access violation.

Tema resuelto, un saludo y gracias
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Llamada a Procedimiento Almacenado desde dentro de un Thread MontarazAE MS SQL Server 2 29-05-2007 17:46:34
Mover posiciones dentro de un list Box creus Varios 13 04-11-2006 18:03:44
Thread bendito thread...se me pierde la ventana Seba.F1 API de Windows 5 02-02-2006 00:16:30
Conocer la posición de un Thread dentro del Listado de ActiveThreads del IdTCPServer R_Richards Internet 2 05-02-2005 23:07:38
TidFTP MaGNa Internet 0 10-01-2005 14:00:10


La franja horaria es GMT +2. Ahora son las 05:19:39.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi