Fórum Estou com um problema serio com uma Thead. #344611
16/08/2007
0
type
TSQL_Thread = class(TThread)
private
FQuery: TClientDataSet;
protected
procedure Execute; override;
public
constructor Create(Query: TClientDataSet);
destructor Destroy; override;
end;
constructor TSQL_Thread.Create(Query: TClientDataSet);
begin
inherited Create(False);
Screen.Cursor := crSQLWait;
FQuery := Query;
FreeOnTerminate := True;
end;
destructor TSQL_Thread.Destroy;
begin
inherited;
Screen.Cursor := crDefault;
end;
procedure TSQL_Thread.Execute;
begin
inherited;
while not Terminated do begin
try
FQuery.Open;
finally
Terminate;
end;
end;
end;
Esse codigo funciona se eu executar um CDS e esperar ele trazer os dados e executar o proximo CDS mais se eu executar dois CDS ao mesmo tempo ele dá AccessViolation
Se eu executar apenas um assim :
TSQL_Thread.Create(CDS1);
Funciona legal agora se eu fizer algo assim :
TSQL_Thread.Create(CDS1);
TSQL_Thread.Create(CDS2);
ai ele dá erro..
O que devo fazer para resolver isso e executar dois ao mesmo tempo ou como fazer uma função que espera trazer os dados do primeiro e já traga os dados do segundo.
Luciano_f
Curtir tópico
+ 0Posts
17/08/2007
Marcosrocha
Gostei + 0
17/08/2007
Luciano_f
Thread Safe que esta dando esse erro
eu estou usando o RemObjects SDK para trazer os dados
eu sei que o RemOBjects é Multi-Thread
Será que terei que usar outro componente ao inves do IBObjects...
Gostei + 0
17/08/2007
Marcosrocha
Mas como Threads são praticamente impossíveis de Debugar, você vai ter que descobrir porque está dando Access Violation...
Eu penso que uma das Threads está matando a outra e por isso access violation, mas não é certeza pois sempre que trabalhei com elas nunca me ocorreu de manipular um CDS nelas...
Gostei + 0
17/08/2007
Luciano_f
tem algum erro nela???
Seguinte na verdade se eu executar uma thread e esperar abrir o CDS e executar o proximo CDS não vai dar erro o erro só acontece se eu abrir dois CDS de uma vez.
Eu tentei fazer uma função que esperace abrir o CDS para abrir o proximo mais não consegui o amigo sabe como posso fazer isso???
Grato.
Gostei + 0
18/08/2007
Marcosrocha
Gostei + 0
19/08/2007
Martins
procedure TSQL_Thread.Execute; begin inherited; while not Terminated do begin try FQuery.Open; finally Terminate; end; end;
Esse código é assim mesmo? Esse [b:13445b4e85]Terminate[/b:13445b4e85] aqui está finalizando a Thread é isso?
Gostei + 0
20/08/2007
Luciano_f
O terminate esta finalizando a Thread.
Mais tanto faz se eu fizer isso aqui
procedure TSQL_Thread.Execute;
begin
inherited;
if Terminated then Exit;
try
FQuery.Open;
finally
Terminate;
end;
end;
Também da o problema
eu precisava fazer um jeito de esperar a Thread terminar para executar uma nova Query eu já tentei varios codigos para isso mais não dá certo.
Gostei + 0
20/08/2007
Massuda
with TSQL_Thread.Create(CDS1) do WaitFor;
Com relação ao Access Violation: isso pode ocorrer se seu código estiver usando um objeto que ainda não foi criado ou que já foi destruído.
Gostei + 0
21/08/2007
Luciano_f
Não teria outra forma de eu poder aguardar a Thread Terminar
Gostei + 0
21/08/2007
Luciano_f
constructor TSQL_Thread.Create(Query: TClientDataSet);
begin
inherited Create(False);
vTerminou := True;
Screen.Cursor := crSQLWait;
FQuery := Query;
FreeOnTerminate := True;
end;
destructor TSQL_Thread.Destroy;
begin
inherited;
Screen.Cursor := crDefault;
Terminate;
vTerminou := False;
end;
procedure TSQL_Thread.Execute;
begin
inherited;
FQuery.Open;
end;
procedure TFrmConsultaCliente.Button1Click(Sender: TObject);
begin
while (CDS1.Active = False) do begin
Application.ProcessMessages;
if (vTerminou = false) then
TSQL_Thread.Create(CDS1);
end;
while (CDS2.Active = False) do begin
Application.ProcessMessages;
if (vTerminou = false) then
TSQL_Thread.Create(CDS2);
end;
End;
A variavel vTerminou está declarada na sessão Private
agora o erro que acontece uma vez ou outra é o seguinte
EInvalidOperation : Canvas does not allow drawing.
O que fazer para resolver esse erro ????
Gostei + 0
21/08/2007
Marcosrocha
Gostei + 0
21/08/2007
Luciano_f
De inicio eu pensei que fosse esse o meu problema mais não é pois
tanto o IBobjects como o RemOBjects são Thread Safe
Na verdade agora eu preciso saber como resolver o erro
[b:10aaf47db6] EInvalidOperation : Canvas does not allow drawing. [/b:10aaf47db6]
Pois o codigo de espera que eu fiz esta funcionando e não é toda hora que esse erro acontece.
Gostei + 0
21/08/2007
Marcosrocha
Já tentou comentar o [b:427f99b83d]Application.ProcessMessages[/b:427f99b83d]?
Porque não tem lógica receber essa mensagem, porém o único método que você está utilizando que possívelmente chama Canvas é o ProcessMessages...
Gostei + 0
21/08/2007
Luciano_f
Application.ProcessMessages Comentado
não funciona simplesmente o codigo não funciona
while (CDS2.Active = False) do begin
//Application.ProcessMessages;
if (vTerminou = false) then
TSQL_Thread.Create(CDS2);
end;
a Thread não funciona ela simplesmente para dentro da
constructor TSQL_Thread.Create(Query: TClientDataSet);
begin
inherited Create(False);
vTerminou := True;
Screen.Cursor := crSQLWait;
FQuery := Query; // é executado até aqui e não vai mais .....
// só com ProcessMessages para funcionar
FreeOnTerminate := True;
end;
Gostei + 0
22/08/2007
Luciano_f
destructor TSQL_Thread.Destroy;
begin
inherited;
Terminate;
end;
procedure TSQL_Thread.Execute;
begin
inherited;
if Terminated then Exit;
try
FQuery.Close;
FQuery.Open;
except
// dentro desse Except não tem codigo algum
// sei que não é certo mais não tive outra alternativa
// a falta disso gera o erro
end;
end;
procedure Proc_ExecQuery(CDS: TClientDataSet);
var Qy_Th: TSQL_Thread;
begin
Qy_Th := TSQL_Thread.Create(CDS);
while (not CDS.Active) and (not Qy_Th.Terminated) do
Application.ProcessMessages;
end;
Eu chamo os CDS com a procedure acima.
Proc_ExecQuery(CDS1);
e Agora não tenho mais erro algum.
e posso executar varios CDS mais sempre vai ter uma espera para abrir os CDS, assim vai abrindo um de cada vez e não congela o aplicativo.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)