Fórum Consulta com Thread #368195
05/02/2009
0
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
Curtir tópico
+ 0Posts
05/02/2009
Diegotiemann
Gostei + 0
07/02/2009
Pestana_
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
Gostei + 0
09/02/2009
Diegotiemann
Este tópicop me ajudou a clarear um pouco as idéas mas ainda não solucionou meu problema.
Gostei + 0
09/02/2009
Ivanh
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;
Gostei + 0
10/02/2009
Rodc
Gostei + 0
10/02/2009
Diegotiemann
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;
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)