Fórum Estou com um problema serio com uma Thead. #344611

16/08/2007

0

Pessoal estou tentando rodar o TClientDataSet em um Thread mais não consigo veja o meu codigo.

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

Luciano_f

Responder

Posts

17/08/2007

Marcosrocha

Luciano os CDS estão conectados ao mesmo banco de dados, você pode criar 300 Threads que serão 300 conexões simultâneas. Só não entendi o por que de trazer os dados dos 2 ao mesmo tempo... :?


Responder

Gostei + 0

17/08/2007

Luciano_f

Jovem no meu caso eu não sei é pelo fato do IBobjects não ser
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...


Responder

Gostei + 0

17/08/2007

Marcosrocha

Acredito que não, já que o CDS está na DataAccess....
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...


Responder

Gostei + 0

17/08/2007

Luciano_f

Meu amigo mais me diga a forma como eu criei essa thread está correta???

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.


Responder

Gostei + 0

18/08/2007

Marcosrocha

Luciano, o seu modo de criação da Thread respeita a herança da classe Thread, logo nao acho que deva ter problemas nela (criação). Sou capaz de apostar que o problema, realmente seja em executar ao mesmo tempo... Quanto a exemplo... não tenho nada para ajudá-lo no momento... Desculpe. :oops:


Responder

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?


Responder

Gostei + 0

20/08/2007

Luciano_f

sim meu amigo é isso mesmo

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.


Responder

Gostei + 0

20/08/2007

Massuda

O terminate esta finalizando a Thread.
O TThread.Terminate existe para que outras threads possam encerrar a thread; ele simplesmente faz TThread.Terminated = True. Não faz muito sentido chamar TThread.Terminate de dentro da thread. A thread é encerrada quando TThread.Execute termina.

eu precisava fazer um jeito de esperar a Thread terminar...
A forma mais simples é usar TThread.WaitFor. Seria algo assim...
with TSQL_Thread.Create(CDS1) do
  WaitFor;
...mas note que isso vai congelar seu programa enquanto aguarda a thread executar.

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.


Responder

Gostei + 0

21/08/2007

Luciano_f

Realmente se vai congelar não resolve, eu já quero usar Thread justamente para o sistema não ficar travado..

Não teria outra forma de eu poder aguardar a Thread Terminar


Responder

Gostei + 0

21/08/2007

Luciano_f

Pessoal eu fiz um codigo aqui que esta case dando certo.

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 ????


Responder

Gostei + 0

21/08/2007

Marcosrocha

Luciano uma vez eu utilizei uma Thread para executar uma rotina pesada no sistema. O problema é que a Thread usava o mesmo IBDataBase da aplicação logo, ao executar a rotina ele fazia com que a aplicação travasse também.


Responder

Gostei + 0

21/08/2007

Luciano_f

McBlade

Luciano uma vez eu utilizei uma Thread para executar uma rotina pesada no sistema. O problema é que a Thread usava o mesmo IBDataBase da aplicação logo, ao executar a rotina ele fazia com que a aplicação travasse também.


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.


Responder

Gostei + 0

21/08/2007

Marcosrocha

[b:427f99b83d] EInvalidOperation : Canvas does not allow drawing. [/b:427f99b83d]

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...


Responder

Gostei + 0

21/08/2007

Luciano_f

Sim eu já fiz isso mais com o
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;


Responder

Gostei + 0

22/08/2007

Luciano_f

Pessoal minha solução foi a seguinte ::::

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
EInvalidOperation : Canvas does not allow drawing.

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.


Responder

Gostei + 0

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

Aceitar