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)
-   -   Este código es super lento (https://www.clubdelphi.com/foros/showthread.php?t=92295)

strelok 20-09-2017 16:37:05

Este código es super lento
 
Hola, os dejo el código aquí abajo:

Resulta que demora y se me congela el formulario 1 o 2 segundos:

Como lo podemos optimizar?
Código Delphi [-]
with DBGridProveedores.DataSource do
  begin
    DataSet.First;
    SetLength(provSelecc, DBGridProveedores.SelectedRows.Count); //Establecer el largo del array
    SetLength(provSeleccNames, DBGridProveedores.SelectedRows.Count); //Establecer el largo del array
    while not DataSet.Eof do
    begin
      if DBGridProveedores.SelectedRows.Find(DataSet.Bookmark, inx) then  //Si la fila fue seleccioanda
      begin
         provSelecc[i] := DBGridProveedores.Columns[0].Field.AsString;  //Guardo en el array
         provSeleccNames[i] := DBGridProveedores.Columns[1].Field.AsString;  //Guardo en el array
         Inc(i);
      end;
      DataSet.Next;
    end;
    //   ShowMessage(IntToStr(length(provSelecc)));  //Muestro cantidad de filas seleccionadas
  end;

AgustinOrtu 20-09-2017 18:10:48

Lo que se me ocurre que podes hacer y que suele mejorar la performance, es deshabilitar el refresco de los componentes visuales mientras realizas tu proceso, y decirle que haga todo de un plumazo al final:

Código Delphi [-]
  DataSet.DisableControls;
  try
    { codigo de procesamiento aca }
  finally
    DataSet.EnableControls;
  end;

Hace tiempo que no trabajo con componentes Data-Aware, no estoy seguro de si hay algun metodo similar en el componente DataSource

Young 20-09-2017 18:11:15

Me parece que 1 o 2 segundos no es mucho dependiendo de la cantidad de registros, lo que si molesta en estas situaciones es que se congele el formulario, por lo tanto te sugiero que lo hagas en una tareas separada:

Código Delphi [-]
uses System.Threading;

.
.

TTask.Run(
    procedure
    begin
with DBGridProveedores.DataSource do begin DataSet.First; SetLength(provSelecc, DBGridProveedores.SelectedRows.Count); //Establecer el largo del array SetLength(provSeleccNames, DBGridProveedores.SelectedRows.Count); //Establecer el largo del array while not DataSet.Eof do begin if DBGridProveedores.SelectedRows.Find(DataSet.Bookmark, inx) then //Si la fila fue seleccioanda begin provSelecc[i] := DBGridProveedores.Columns[0].Field.AsString; //Guardo en el array provSeleccNames[i] := DBGridProveedores.Columns[1].Field.AsString; //Guardo en el array Inc(i); end; DataSet.Next; end; // ShowMessage(IntToStr(length(provSelecc))); //Muestro cantidad de filas seleccionadas end;
end);

¿Por otro lado porque haces la operacion sobre el dbgrid y no sobre el dataset?

Saludos.

strelok 20-09-2017 18:33:59

Muchas gracias a ambos, sin embargo, parece que le erré, no es esa la función que causa que el formulario se congele entre 1 y 2 segundos.
Es cuando llamo al procedimiento relacionarProv
¿Puedo hacer lo siguiente?

Código:

        TTask.Run(
          procedure
          begin
              relacionarProv;
          end);


mamcx 20-09-2017 18:35:36

Y que hace relacionarProv?

strelok 20-09-2017 18:44:21

Código Delphi [-]
var
inicio, fin : Integer;
begin
    inicio := 1;      //Empiezo de la 1, porque 0 es el título de columna
    fin := vlRelacionarProveedores.RowCount; //Cantidad de filas
    SetLength(self.provBDprovHojaCal, fin, 2); //Seteo alto y ancho del array
    while(inicio < fin) and (vlRelacionarProveedores.Cells[1, inicio] <> '')  do
    begin
        self.provBDprovHojaCal[inicio-1, 0] := vlRelacionarProveedores.Cells[0, inicio]; //Guardo columna 1
        self.provBDprovHojaCal[inicio-1, 1] := extraerIDProveedor(vlRelacionarProveedores.Cells[1, inicio]); //Guardo columna 2  ID
        Inc(inicio);
    end;
    SetLength(self.provBDprovHojaCal, inicio-1, 2); //Ajustar el array a los elementos insertados
end;


Resulta que fin = 2, porque solo estoy relacionando 2 mmmm...

ecfisa 20-09-2017 21:25:23

Hola.

Para detectar el motivo de la demora, también sería necesario ver el código de la función extraerIDProveedor (así como también conocer con cuantos registros estas trabajando).

Saludos :)

Casimiro Notevi 20-09-2017 23:30:29

Y también sería necesario saber qué estás haciendo y qué quieres conseguir.

AgustinOrtu 21-09-2017 01:48:23

El problema es que meter en hilos en segundo plano codigo que actualiza la interfaz de usuario te va a traer problemas de sincronizacion, ya que solo el hilo principal (es decir, en donde corre la Vcl) se pueden actualizar los controles.

Para poder usar hilos debes separar completamente los datos de tu interfaz grafica, de esta manera podes procesarlos en segundo plano y luego actualizar cuando este procesamiento termina

Neftali [Germán.Estévez] 21-09-2017 08:23:28

De primeras decir que das pocos datos para hablar de rendimiento.
Es decir, lo lento o rápido de este código, aparte del código dependerá de qué tipo de consulta estás utilizando, números de registros, qué tipo de cursos estás utilizando,...

Por otro lado, sin saber muy bien lo que quieres obtener, hay una línea que no me queda clara:

Código Delphi [-]
      if DBGridProveedores.SelectedRows.Find(DataSet.Bookmark, inx) then  //Si la fila fue seleccioanda

¿Si ya estás recorriendo los "seleccionados", porqué haces un Find para ver si la línea está seleccionada (segun el comentario)?
Revisa la ayuda sobre GotoBookmark.

strelok 21-09-2017 09:07:55

El extraerID se los dejó por aquí:


Código:

var
IDprov: String;
i: Integer;
begin
  IDprov := '';
  i := 0;

  for i:= 1 to length(dato) do
  begin
      if(dato[i] = '-') then Break
      else IDprov := IDprov + dato[i];
  end;

  result := IDprov;
end;


mamcx 21-09-2017 15:52:21

Aparte de todo, yo diria que meter hilos en si mismo es un problema. Un algoritmo secuencial deberia ser rapido antes de pensar en ponerlo paralelo (ademas que es poco comun que se usen hilos correctamente).

-----

Una optimizacion obvia si la idea es marcar que filas estan o no seleccionadas es reaccionar al evento de "seleccion/des-seleccion" de forma directa y actualizar el array, no al final en batch. Esto deberia SUSTANCIALMENTE reducir los tiempos.

strelok 21-09-2017 16:03:18

Tienes razón, voy a intentarlo y comento más tarde o mañana.

Gracias a todos.


La franja horaria es GMT +2. Ahora son las 17:10:07.

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