Ver Mensaje Individual
  #1  
Antiguo 31-05-2013
ElGatitoTapatio ElGatitoTapatio is offline
Miembro
 
Registrado: nov 2006
Posts: 38
Reputación: 0
ElGatitoTapatio Va por buen camino
Hilos: Excepcion al cerrar la aplicacion

Buen día para todos, llevo 2 días tratando de agregar un Hilo a mi aplicacion para realizar un proceso de copiado de archivos. Me explico un poco, estoy desarrollando un sistema el cual tenga la posibilidad de enviar a un servidor archivos que fueron grabados de forma local y temporal en el equipo. Este proceso quiero que se ejecute sin que mi aplicacion se detenga a que termine el proceso, por lo tanto lo metí a un hilo. El problema es el siguiente, el hilo se ejecuta correctamente, es decir, si copia los archivos si es que existen, pero cuando cierro mi aplicacion me genera una excepcion de memoria (Access Violation). La verdad es que no tengo experiencia con hilos, en realidad es mi primer hilo, por lo tanto pido de su ayuda para localizar mi ERROR. Les anexo mi codigo. (cabe señalar que la excepcion solo ocurre cuando si encontro y copio los archivos)

Unidad donde declaro el hilo:

Código Delphi [-]
unit uHilos;

interface

uses
  Classes, ExtCtrls, Windows, ComCtrls, System.SysUtils, StrUtils, ShellApi;

type
  TEnviarTemporales = class( TThread )
  private
    Handle : HWND;
  protected
    function  CopiarDocumentos(destino,ruta : String): Integer;
    procedure EnviarDocumentos;
    procedure Execute; override;
  public
    constructor Create(EHandle:HWND; ThreadPriority: TThreadPriority);
  end;

implementation

uses main;

function TEnviarTemporales.CopiarDocumentos(destino,ruta : String): Integer;
var
    F : TShFileOpStruct;
    sOrigen, sDestino : String;
begin
    Result := 0;
    sOrigen := destino+ #0;
    sDestino := ruta+ #0;

    with F do
    begin
      Wnd   := Handle;
      wFunc := FO_COPY;
      pFrom := @sOrigen[1];
      pTo   := @sDestino[1];
      fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_SIMPLEPROGRESS or FOF_NOERRORUI;
    end;

    Result:= ShFileOperation(F);
end;


procedure TEnviarTemporales.EnviarDocumentos;
var
   NetResource: TNetResource;
   vRuta,NuevaRuta : PChar;
   Error,Diagonal : String;
   ErrCode,i : integer;
   Listado,ListadoEliminar : TStrings;
begin
   with ServidorAlmacenamiento,frm_main do   // ServidorAlmacenamiento es una variable de tipo registro donde guardo info del servidor asi mismo si esta o no activa
    begin
       Listado:= TStringList.Create;
       ListadoEliminar:= TStringList.Create;
       if not Activo then Exit;

       // ++ Buscar si hay documentos temporales
       ArchivosdeRuta(AlmacenamientoTemporal,Listado);    // Funcion para regresar los archivos que se encontraron y los guarda en la variable Listado
       if Listado.Count = 0 then Exit;     // Si esto ocurre, es decir, si no hubo archivos entonces se sale y por ende termina el hilo y no ocurre el error, el problema es cuando continua 

       StatusBar.Panels.Items[2].Text:= 'Transfiriendo documentos temporales...';

       vRuta:= PChar(Ruta);

       NetResource.dwType := RESOURCETYPE_DISK;
       NetResource.lpLocalName := nil;
       NetResource.lpRemoteName := vRuta;
       NetResource.lpProvider := nil;

       // ++ Si el almacenamiento no es el temporal
       if not Local and not Abierto then
        begin
           if (Usuario = '') then ErrCode := WNetAddConnection2(NetResource, nil, nil, CONNECT_TEMPORARY)
            else ErrCode := WNetAddConnection2(NetResource, PChar(Pass), PChar(Usuario), CONNECT_TEMPORARY);

           case ErrCode of
             5 : Error:= 'ERROR_ACCESS_DENIED';
             85 : Error:= 'ERROR_ALREADY_ASSIGNED';
             67 : Error:= 'ERROR_BAD_NET_NAME';
             86 : Error:= 'ERROR_INVALID_PASSWORD';
             1203 : Error:= 'ERROR_NO_NET_OR_BAD_PATH';
             1222 : Error:= 'ERROR_NO_NETWORK';
            else Error:= IntToStr(ErrCode);
           end;

           if ErrCode <> 0 then
            begin
              Mensaje(3,-1,'','Error al conectar al servidor de almacenamiento. ('+Error+')');
              hLog('Error al conectar al servidor de almacenamiento. ('+Error+')');
            end;
        end;
       // ++ Intentar copiar los archivos
       Try
         if AlmacenamientoTemporal[Length(AlmacenamientoTemporal)] <> '\' then Diagonal := ''      // Almacenamiento temporal contiene la ruta local de los archivos
          else Diagonal:= '\';

         for i := 0 to Listado.Count-1 do
          begin
            NuevaRuta:= PChar(vRuta+AnsiReplaceStr(Listado[i],frm_main.AlmacenamientoTemporal,Diagonal));;
            // ++ Verificar si existe el archivo y respaldar version actual
            if FileExists(NuevaRuta) then
              begin
                ErrCode:= CopiarDocumentos(NuevaRuta,AnsiReplaceStr(NuevaRuta,ExtractFileExt(NuevaRuta),FormatDateTime('_ddmmy  yyy_hhnnss',Now)+ExtractFileExt(NuevaRuta)));
                if ErrCode <> 0 then hLog('No se pudo respaldar la version del archivo. ('+NuevaRuta+')('+IntToStr(ErrCode)+')');
               end;
            // ++ Copiar los documentos
            ErrCode:= CopiarDocumentos(PChar(Listado[i]),NuevaRuta);
            if ErrCode <> 0 then hLog('No se pudo transferir el archivo al servidor de almacenamiento. ('+NuevaRuta+')('+IntToStr(ErrCode)+')')
              else
                begin
                  if DBConectada then RegistrarActividad(26,-1,GetPCName,MidStr(ExtractFileName(NuevaRuta),1,30));
                  ListadoEliminar.Add(Listado[i]);
                 end;
          end;
        // ++ Eliminar archivos copiados
        XDel(Handle,ListadoEliminar);
        StatusBar.Panels.Items[2].Text:= '';
       Except
          On E: Exception do
            begin
              StatusBar.Panels.Items[2].Text:= '';
              hLog('Error al transferir los documentos al servidor de almacenamiento.('+E.Message+')');
            end;
       End;
       // ++ Desconectar el acceso
       if not Local and not Abierto then
        ErrCode := WNetCancelConnection2(vRuta, CONNECT_UPDATE_PROFILE, True);
       Listado.Free;
       ListadoEliminar.Free;
    end;
end;

procedure TEnviarTemporales.Execute;
begin
  Synchronize(EnviarDocumentos);
  Terminate;
end;

constructor TEnviarTemporales.Create(EHandle:HWND; ThreadPriority: TThreadPriority);
begin
  inherited Create(False);
  Handle:= EHandle;
end;

end.

Y esto es lo que tengo declarado en el formulario principal:

Código Delphi [-]
Var
  HEnviarTemporales  : TEnviarTemporales; // Hilo para el envio de temporales

...

procedure Tfrm_main.FormDblClick(Sender: TObject);
begin
  EnviarTemporales;
end;

...
procedure Tfrm_main.EnviarTemporales;
begin
  HEnviarTemporales:= TEnviarTemporales.Create(Handle, tpNormal);
  //HEnviarTemporales.FreeOnTerminate:= True;
end;

Como podrán ver hago la prueba de la ejecucion del hilo cuando doy doble clic a la forma.

ustedes siempre me sacan de broncas, por favor ayudenme nuevamente!!! ya me comienza a doler el coco...

Gracias y saludos!!!
Responder Con Cita