Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Tiempo de espera.- (https://www.clubdelphi.com/foros/showthread.php?t=50188)

BuenaOnda 10-11-2007 21:59:01

Tiempo de espera.-
 
Hola amigos..

Nuevamente recurro a uds, para ver si me pueden ayudar a solucionar un problemilla que tengo, resulta que ejecuto una consulta en Firebird, esta consulta demora 50 segundos aprox. en mostrar los resultados, entonces lo que hago desde delphi es mostrar un "Reloj" que me muestra el tiempo transcurrido en la consulta, pero el programa se queda pegado hasta que la consulta se ejecuta y muestra los resultados( utilizo los componentes IBX). Existe alguna propiedad en los componentes IBX que me permita realizar algo asi como un Application.ProcessMessages o algo por el estilo para que me programa no se quede "pegado", muchas gracias por su ayuda..:D.

esta es la consulta..

Código SQL [-]
SELECT M.CODIGO_FAMILIA,COALESCE( SUM( ( (COALESCE(SUM(M.DIAS_C + M.MASDIAS),0)) * M1.CANCELADO) / M1.DIAS_ARR),0) AS CANCELADO,
       COALESCE(SUM(M.DIAS_C + M.MASDIAS),0) AS DIAS
  FROM(SELECT A.CODIGO_FAMILIA,C.dias_arrendado  AS DIAS_C,C.CODIGO_CONTRATO,
              CASE WHEN C.FECHA_TERMINO < C.FECHA_INICIO
                   THEN 'NOW' - C.FECHA_INICIO 
                   ELSE 0 END AS MASDIAS
         FROM FAMILIA A,RL_FACTURA_DE_VENTAS_CONTRATOS D,
              DETALLE_CONTRATOS_DE_ARR C, FACTURA_DE_VENTAS E,MAQUINAS F
        WHERE C.CODIGO_CONTRATO=D.CODIGO_CONTRATO
          AND D.CODIGO_FACTURA_DE_VENTA=E.CODIGO_FACTURA_DE_VENTA
          AND (E.ANULADA='N' AND E.HISTORICA='N')
          AND C.CODIGO_MAQUINA=F.CODIGO_MAQUINA 
          AND A.CODIGO_FAMILIA=F.CODIGO_FAMILIA
          AND D.FECHA_FACTURACION >='01-JUL-2007'
        GROUP BY A.CODIGO_FAMILIA,DIAS_C,C.CODIGO_CONTRATO,MASDIAS)M
    LEFT JOIN(SELECT C.CODIGO_CONTRATO,COALESCE(SUM(C.dias_arrendado),0) DIAS_ARR,
                     COALESCE(SUM(D.VALOR_CANCELADO),0) AS CANCELADO
                FROM DETALLE_CONTRATOS_DE_ARR C,
                     RL_FACTURA_DE_VENTAS_CONTRATOS D
               WHERE C.CODIGO_CONTRATO=D.CODIGO_CONTRATO
               GROUP BY C.CODIGO_CONTRATO) AS M1
              ON M.CODIGO_CONTRATO=M1.CODIGO_CONTRATO
GROUP BY M.CODIGO_FAMILIA

BuenaOnda 11-11-2007 20:14:52

existe otro componente de conexion a base de datos que me permita hacer esto?.. (aunq' me imagino que es el firebird el que provoca esto)..cualquier aporte se los agradecere mucho..:D

Neftali [Germán.Estévez] 12-11-2007 10:19:51

Si el problema es que la consulta tarda mucho, no creo que se solucione con componentes de conexión; De todas formas yo optaría:

1º) Como primera opción intentar reducir el tiempo de la consulta; Revisar los índices que tienes creados para optimizar, intentar crear un Stored Procedure que te realice la misma consulta,...

2º) Tema aplicación; No se los componentes que estás utilizando, se que hay algunos que permiten ejecutar consultas en modo asíncrono; Revisa si los que utilizas poseen esa opción. Con esto conseguirás que el control vuelva al programa mientras se lanza la consulta
y se recuperan los datos.

tefots 12-11-2007 14:58:41

tambien puedes crear un thread
y en el execute del thread realizar la consulta

eso si , se recomienda que el thread tenga su propio tibdatabase y su tibtransaction.

duilioisola 12-11-2007 18:51:49

Podrías poner un TTimer y una variable global que tenga la hora en que se inició el select.

Poner el Timer a 1 segundo.

En el procedimiento que ejecuta select, activar el timer.
Código Delphi [-]
[...]
Tiempo := Now;
Timer1.Enabled := True;
Table.Open;
[...]
OnTimer poner algo asi:

Código Delphi [-]
begin
   ProgressBar.StepIt;
  Application.ProcessMessage;
end;
o
Código Delphi [-]
begin
   LabelTiempo.Caption := 'Tiempo transcurrido: '+DateTimeToStr(Now-Tiempo);
  Application.ProcessMessage;
end;

BuenaOnda 13-11-2007 02:36:42

Gracias por sus respuestas..
 
lo que dice duilioisola es lo que estoy haciendo, pero la consulta , al ejecutarse, no permite que se refresque el timer, eso es lo que busco solo poder refrescar el timer, para mostrar el tiempo transcurrido..muchas gracias por su ayuda compañeros..

BuenaOnda 13-11-2007 03:09:05

Utilizo los componentes de la paleta "Interbase"(IBDataBase,IBTransacction,IBQuery...)..

duilioisola 13-11-2007 08:46:53

Puedes poner el código que tienes dentro de OnTimer, para poder ver porqué no refresca el timer.
Quizás te podamos ayudar si vemos un error o una omisión o ... quién sabe qué.

boreg 14-11-2007 00:14:44

Saludos, supongo que lo que hace falta es usar el metodo refresh del formulario (Formulario.refresh;) que redibuja el formulario completo con el OnTimer, es solo una suposicion la verdad es que me estoy iniciando en la programacion con delphi y no le se mucho al respecto.
Espero sea de ayuda SUERTE!!!!!

BuenaOnda 14-11-2007 02:00:57

Hola...
Este es el Código del Timer..


Código Delphi [-]
procedure TfrmMontosFacturadosPorFamilia.Timer1Timer(Sender: TObject);
begin
     Application.ProcessMessages;
     Tiempo:=Tiempo + 0.00001;
     lblTiempo.Caption:=FormatDateTime('hh:nn:ss',Tiempo);
     lblTiempo.Refresh;
     Application.ProcessMessages;
end;

Gracias por sus respuestas compañeros..

duilioisola 14-11-2007 09:10:38

En el procedimiento veo un error al darle formato a lblTiempo.Caption.
Los minutos están puesto con dos "N" y deben ser dos "M".

De todos modos, yo haría lo siguiente:

La variable Tiempo debe ser global. O sea, definida en la parte Private o Public del Form.

Código Delphi [-]
   public
      Tiempo : TDateTime;
Justo antes de ejecutar la consulta pones la variable Tiempo a la hora actual y activas el timer.
Código Delphi [-]
   [...]
   Tiempo := Now;
   Timer1.Enabled := True;
   Table.Open;   
   Timer1.Enabled := False;
   [...]
En el procedimiento OnTimer, cada vez que se ejecuta, debes deshabilitarlo, por las dudas tarde demasiado en ejecutarse y se ejecute otra vez antes de terminar la primera ejecución. Al finalizar lo que deba hacer lo habilitas nuevamente.

Lo que debes mostrar luego es la diferencia entre la hora actual y la hora a la que lo lanzaste (Now-Tiempo)

Recuerda lo que dije antes del formato "hh:mm:ss"
Código Delphi [-]
procedure TfrmMontosFacturadosPorFamilia.Timer1Timer(Sender: TObject);
begin
     Timer1.Enabled := False;
     lblTiempo.Caption:=FormatDateTime('hh:mm:ss',Now-Tiempo);
     lblTiempo.Refresh;
     Application.ProcessMessages;
     Timer1.Enabled := True;
end;

Dime si ahora, con este cambio te sale bien...

BuenaOnda 15-11-2007 03:25:20

eso es lo que hago..(este formato 'hh:nn:ss' si funciona), lo que pasa es que al ejecutar la consulta SQL el evento OnTimer no se ejecuta, gracias por tu respuesta..:)

Lepe 15-11-2007 12:24:14

Es un problema muy común. Mientras está buscando los datos en la base de datos, no podrás hacer nada.

Una solución es crear un Thread (un segundo hilo de ejecución) y ahí muestras el tiempo o lo que necesites. Obviamente tienes que crear y lanzar el thread y después abrir el sql.

Por otra parte 50 segundos me parece mucho. Marathon es un programa gratuito como Ib Expert, que permite ver el plan de ejecución de una consulta, estudiando eso, puedes saber si utiliza índices y claves primarias para la unión y selección de datos, o utiliza el plan "NATURAL".

duilioisola: Para el formato de hora, MM se utiliza para el mes en dos dígitos, como esas letras ya están pilladas, se usa nn para minutos. Cierto que usando hh:mm:ss no da error y muestra "aparentemente la hora", pero verás que los minutos se actualizan una vez al mes ;) :D :p

Edito: Al parecer no he dicho nada nuevo, Neftali y tefots ya te lo dijeron (no leí el hilo al completo). El camino por el que vas no es el correcto.

Además, ¿para qué quieres mostrar un cronómetro?, ¿para que los usuarios vean lo ineficiente que es tu programa y así decir que tarda 53.88 segundos :p?.

Saludos

BuenaOnda 16-11-2007 03:12:32

Cita:

Además, ¿para qué quieres mostrar un cronómetro?, ¿para que los usuarios vean lo ineficiente que es tu programa y así decir que tarda 53.88 segundos :p?.

gracias por el aporte..jajajaj.

muchas gracias por sus respuestas.. ya me habia planetado utilizar un thread, y parece que es lo que me queda por hacer.


La franja horaria es GMT +2. Ahora son las 16:17:03.

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