GARANTIR DESCONTO

Fórum Consulta com Thread #368195

05/02/2009

0

Olá

Estou enfrentando problemas na criação de uma thread para a realização de
consultas dinamicas.

Tenho um programa 3 camadas no qual algumas consultas ficam lentas pela internet, ou seja demora para abrir o Form.

Então criei a seguinte Classe:
unit uThreads;

interface

uses
  Classes, DB, DBClient, FORMS;

type
  uThreadDesempenho = class(TThread)
  private
   CDS :TClientDataSet;
   SQL :string;
  protected
    procedure Execute; override;
    procedure ExecuteSQL;
public
    constructor Criar(CDS :TClientDataSet; pSQl:String);
end;


implementation
  uses uFuncoes;
 constructor uThreadDesempenho.Criar(CDS :TClientDataSet; pSQl:String);
begin
   Create(False);
   Self.CDS := CDS;
   SQl :=  pSQL;
   FreeOnTerminate := True;
end;



 procedure uThreadDesempenho.ExecuteSQL;
 begin
  CDS.Data := ReturnSQL(SQL);
 end;


procedure uThreadDesempenho.Execute;
begin
   Synchronize(ExecuteSQL);
end;

end.


E estou chamando a Thread no on Show do form:

  returnSQL é uma função que está no servidor que retorna um Olevariant

var
  SQL : string;
   Thread :  uThreadDesempenho;
begin
      Thread :=   uThreadDesempenho.Criar(cdsVisualizaColeta, SQL);
end;
  


Mas o problema é que dessa maneira o form aparece na tela mas alguns componentes visuais não aparece, os nenhum clique em botão funciona, até que a thred tenha sido executada.

OBS:A thread retorna os dados da consulta, mas parece que a tela esta trancada, já testei colocar application.processmessages, mas não funcionou.

O que pode ser? Não conseço nada de threads;


Diegotiemann

Diegotiemann

Responder

Posts

05/02/2009

Diegotiemann

Ninguém se habilita?


Responder

Gostei + 0

07/02/2009

Pestana_

colega eu tambem estou aprendendo Thread.

de uma olhada neste [url=http://www.activedelphi.com.br/forum/viewtopic.php?p=243894#243894]tópico[/url] que eu postei, talvez te ajude.

boa sorte!
Pestana


Responder

Gostei + 0

09/02/2009

Diegotiemann

Obrigado pela indicação

Este tópicop me ajudou a clarear um pouco as idéas mas ainda não solucionou meu problema.


Responder

Gostei + 0

09/02/2009

Ivanh

[b:621faf51cf]Soh funciona em Delphi Enterprise no Pro nao[/b:621faf51cf]

  
TFriendLocalConnection = class(TLocalConnection);

TOpenCDSThread = class(TThread)
    FlDB       : TSQLConnection;
    FQry       : TSQLQuery;
    FDSP       : TDataSetProvider;
    FLocalCon  : TLocalConnection;
    FCDS       : TClientDataSet;
    FCDSOrigem : TClientDataSet;
    FError     : String;
  protected
    procedure Execute; override;
    procedure UpdateCDS;
    procedure UpdateError;
  public
    Running    : Boolean;
    FOwnerForm : TCustomForm;
    constructor Create(ADB : TSQLConnection; AQry : TSQLQuery; ADSP : TDataSetProvider; ACDS: TClientDataSet);
    destructor Destroy; override;
  end;


O resto

constructor TOpenCDSThread.Create(
  ADB: TSQLConnection;
  AQry : TSQLQuery;
  ADSP : TDataSetProvider;
  ACDS : TClientDataSet);
var
  lConnectionHandle,i : integer;
  lTmpField           : TField;
begin
  inherited Create(true);
  FlDB := TSQLConnection.Create(nil);
  FlDB.LoadParamsOnConnect := False;
  FlDB.LoginPrompt := False;
  FlDB.DriverName := ADB.DriverName;
  FlDB.ConnectionName := ADB.ConnectionName;
  FlDB.Name := ADB.Name + ´MyClone´;
  FlDB.Params.AddStrings(ADB.Params);
  FlDB.GetDriverFunc := ADB.GetDriverFunc;
  FlDB.LibraryName := ADB.LibraryName;
  FlDB.VendorLib := ADB.VendorLib;
  FlDB.TableScope := ADB.TableScope;

  //Para poder cancelar a consulta depois FB2.1
  lConnectionHandle := GetSQLFmt(FlDB,´SELECT CURRENT_CONNECTION FROM RDB$DATABASE´,[]);

  dialogo.IniciaProgressDialog(ACDS.Owner,lConnectionHandle,ADB);

  //Criando uma nova qry
  FQry               := TSQLQuery.Create(nil);
  FQry.SQLConnection := FlDB;
  FQry.SQL.Text      := AQry.SQL.Text;

  //Persistindo os campos e copiando os providerflags e outros...
  AQry.FieldDefs.Update;
  FQry.FieldDefs     := AQry.FieldDefs;
  for i:=0 to FQry.FieldDefs.Count-1 do
  begin
    with FQry.FieldDefs[i].CreateField(FQry) do
    begin
      lTmpField := AQry.FindField(FieldName);
      if Assigned(lTmpField) then
      begin
        ProviderFlags := lTmpField.ProviderFlags;
        ReadOnly      := lTmpField.ReadOnly;
        Required      := lTmpField.Required;
      end;
    end;
  end;

  FDSP                := TDataSetProvider.Create(nil);
  FDSP.DataSet        := FQry;
  FDSP.Name           := ´dspLocal´;
  FDSP.UpdateMode     := ADSP.UpdateMode;
  FDSP.OnGetTableName := ADSP.OnGetTableName;

  FLocalCon         := TLocalConnection.Create(Application);
  TFriendLocalConnection(FLocalCon).RegisterProvider(FDSP);

  FCDS              := TClientDataSet.Create(nil);
  FCDS.RemoteServer := FLocalCon;
  FCDS.ProviderName := ´dspLocal´;
  FCDSOrigem        := ACDS;
  Priority          := tpLower;
end;

destructor TOpenCDSThread.Destroy;
begin
  FCDS.Free;
  FCDSOrigem := nil;  
  FLocalCon.Free;
  FDSP.Free;
  FQry.Free;
  FlDB.Free;
  inherited;
end;

procedure TOpenCDSThread.Execute;
begin
  Running := true;
  try
    FCDS.Open;
    if Terminated then Exit;
    Synchronize(UpdateCDS);
  except
    on e:exception do
    begin
     FError := e.Message;
     Synchronize(UpdateError);
    end;
  end;
  Running := false;
end;


procedure TOpenCDSThread.UpdateCDS;
begin
  FCDSOrigem.CloneCursor(FCDS,false,false);
  dialogo.EncerraProgressDialog;
end;


procedure TOpenCDSThread.UpdateError;
begin
  dialogo.ShowError(FError);
end;



Responder

Gostei + 0

10/02/2009

Rodc

Não adianta nada você fazer uma thread se o processamento dela você faz usando Syncronize(). O Syncronize faz com que o processamento da função seja executado no processo principal da aplicação e não no processo da thread que você acabou de criar. Resumindo, a consulta continua sendo executada pelo processo geral e, consequentemente, continua travando sua aplicação.


Responder

Gostei + 0

10/02/2009

Diegotiemann

Não adianta nada você fazer uma thread se o processamento dela você faz usando Syncronize(). O Syncronize faz com que o processamento da função seja executado no processo principal da aplicação e não no processo da thread que você acabou de criar. Resumindo, a consulta continua sendo executada pelo processo geral e, consequentemente, continua travando sua aplicação.


Isso que você falou eu sei, o que eu não sei é como solucionar este problema, pois se removo o Syncronize ocorre um erro na linha.
  CDS.Data := ReturnSQL(SQL); 


Abaixo o código da função ReturnSQL, função que chama uma função de mesmo nome no servidor:
Function ReturnSQL(SQL:String):Olevariant;
begin
  Result:=DM.sckConnServer.AppServer.ReturnSQL(SQL);
end;


Abaixo a função no servidor:
function TClasseConnection.ReturnSQL(var CommandSQL: OleVariant): OleVariant;
var
  SQL : TSQLDataSet;
  DSP : TDataSetProvider;
  CDS : TClientDataSet;
begin

  SQL := TSQLDataSet.Create(Self);
  DSP := TDataSetProvider.Create(Self);
  CDS := TClientDataSet.Create(Self);

  SQL.SQLConnection := FrmServer.SQLConn;
  SQL.GetMetadata   := False;
  SQL.Name          := ´SQL´;

  DSP.Name          := ´DSP´;
  DSP.DataSet       := SQL;
  DSP.Options       := [poAllowCommandText, poReadOnly, poPropogateChanges, poAutoRefresh];

  CDS.Name          := ´CDS´;
  CDS.ProviderName  := ´DSP´;
  CDS.CommandText   := CommandSQL;

  try
    CDS.Open;
    Result := CDS.Data;
    CDS.Close;
  except
    Result := -1;
    SQL.Free;
    DSP.Free;
    CDS.Free;
    raise EDatabaseError.Create(´Erro de Retorno de Execução de SQL: ´ + 13 + CommandSQL);
  end;

  SQL.Free;
  DSP.Free;
  CDS.Free;



Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar