 |
ActiveDelphi .: O site do programador Delphi! :.
|
| Exibir mensagem anterior :: Exibir próxima mensagem |
| Autor |
Mensagem |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Sex Jan 30, 2009 9:17 pm Assunto: Thread - ProgressBar |
|
|
Alguem saberia me dizer o que tem de errado neste código? porque a thread não esta resolvendo o problema de congelamento da tela.
Estou tentando executar o Progressbar no form principal atraves de uma thread.
A inteção é de deixar o ProgressBar rodando (igual a inicialização do windows XP) mesmo que seja aberto a query segue a unit de exemplo:
| Código: | unit Principal;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, IBCustomDataSet, IBQuery, IBDatabase, ComCtrls, StdCtrls,
ExtCtrls, Grids, DBGrids, ThreadProgressbar;
type
TfrmPrincipal = class(TForm)
DBGrid1: TDBGrid;
Panel1: TPanel;
btnExecutarQuery: TButton;
btnFecharQuery: TButton;
ProgressBar1: TProgressBar;
IBDatabase1: TIBDatabase;
IBTransaction1: TIBTransaction;
IBQuery1: TIBQuery;
DataSource1: TDataSource;
procedure btnExecutarQueryClick(Sender: TObject);
procedure btnFecharQueryClick(Sender: TObject);
procedure IBQuery1BeforeOpen(DataSet: TDataSet);
private
{ Private declarations }
procedure ExecutarProgressBar(executa : boolean);
public
{ Public declarations }
end;
var
frmPrincipal : TfrmPrincipal;
thrProgressbar : TThreadProgressbar;
implementation
{$R *.dfm}
procedure TfrmPrincipal.ExecutarProgressBar(executa : boolean);
begin
if executa then
thrProgressbar := TThreadProgressbar.Create(false)
else
if thrProgressbar <> nil then
begin
thrProgressbar.Terminate;
thrProgressbar := nil;
end;
end;
procedure TfrmPrincipal.IBQuery1BeforeOpen(DataSet: TDataSet);
begin
ExecutarProgressBar(true);
end;
procedure TfrmPrincipal.btnExecutarQueryClick(Sender: TObject);
begin
IBQuery1.Open;
ExecutarProgressBar(false);
end;
procedure TfrmPrincipal.btnFecharQueryClick(Sender: TObject);
begin
IBQuery1.Close;
end;
end. |
na unit da thread:
| Código: | unit ThreadProgressbar;
interface
uses
Classes;
type
TThreadProgressbar = class(TThread)
private
{ Private declarations }
procedure InicializaProgressbar;
procedure AndamentoProgressbar;
procedure VisualizarProgressbar(visual : boolean);
protected
procedure Execute; override;
procedure Termino(Sender : TObject);
public
constructor Create(CreateSuspended : boolean);
end;
implementation
uses Principal;
constructor TThreadProgressbar.Create(CreateSuspended : boolean);
begin
inherited Create(CreateSuspended);
OnTerminate := Termino;
FreeOnTerminate := True;
Priority := tpLower;
end;
procedure TThreadProgressbar.Termino(Sender : TObject);
begin
VisualizarProgressbar(false);
end;
procedure TThreadProgressbar.Execute;
begin
Synchronize(InicializaProgressbar);
while not Terminated do
Synchronize(AndamentoProgressbar);
end;
procedure TThreadProgressbar.InicializaProgressbar;
begin
with frmPrincipal.ProgressBar1 do
begin
VisualizarProgressbar(true);
Position := 0;
Min := 0;
Max := 10;
end;
end;
procedure TThreadProgressbar.AndamentoProgressbar;
begin
with frmPrincipal.ProgressBar1 do
begin
if Position < Max then
Position := Position+1
else
Position := 0;
end;
end;
procedure TThreadProgressbar.VisualizarProgressbar(visual : boolean);
begin
frmPrincipal.ProgressBar1.Visible := visual;
end;
end. |
_________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso.
Editado pela última vez por pestana em Qui Fev 05, 2009 10:25 am, num total de 3 vezes |
|
| Voltar ao Topo |
|
 |
aeciovc Colaborador

Registrado: Terça-Feira, 18 de Dezembro de 2007 Mensagens: 1042 Localização: Recife
|
Enviada: Sex Jan 30, 2009 9:48 pm Assunto: |
|
|
Cara...
tenho um exemplo de Threads aki num sei se te ajudaria!!
se quiser passa teu email!!!
flw |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Sex Jan 30, 2009 9:51 pm Assunto: |
|
|
Agradeço se você enviar pra mim [ rogerio_pestana@yahoo.com.br ]
Atenciosamente,
Pestana. _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
mestrehurricane Mestre


Registrado: Domingo, 14 de Janeiro de 2007 Mensagens: 984 Localização: Belo Horizonte - MG
|
|
| Voltar ao Topo |
|
 |
gilsonnrodrigues Moderador

Registrado: Quinta-Feira, 14 de Abril de 2005 Mensagens: 9009 Localização: Governador Valadares-MG
|
Enviada: Seg Fev 02, 2009 11:56 am Assunto: |
|
|
observe esse código:
| Código: | procedure TThreadProgressbar.Execute;
begin
Synchronize(InicializaProgressbar);
while not Terminated do
Synchronize(AndamentoProgressbar); |
em especial a linha
| Código: | | Synchronize(AndamentoProgressbar); |
vc ta executando o metodo AndamentoProgressbar dentro de Synchronize q faz com q o tal metodo seja executado pelo processo principal.
e se o processo principal ta ocupado executando alguma coisa, a execução do metodo vai ficar condicionada à disponibilidade do processo principal.
agora é o seguinte, o processo de pintura tem q ser executado pelo processo principal mesmo. ou seja, se vc quer q a tela não trave, vc não deve prender o processo principal.
ou seja, a thread deveria fazer o pesado e o principal atualizar a pintura, porem vc ta fazendo ao contrario. |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Seg Fev 02, 2009 10:27 pm Assunto: |
|
|
boa noite Gilson!
Você tem razão, não faz sentido este código, deixar a thread executar o preenchimento do progressbar e o processo principal executar o pesado, é a primeira vez que estou tentando entender como é o funcionamento de uma thread e agora você clareou o que estava obscuro pra mim!
A minha inteção era de ficar preenchendo o progressBar continuamente (igual ao progressBar do Windows XP na inicialização) até que o processo principal conclua a execução da instrução SQL, sabendo que se eu tentar preecher o progressBar utilizando o processo principal, não vai dar certo porque o mesmo vai estar ocupado com a instrução SQL.
Achei interessante este seu exemplo de deixar que a thread execute o SQL, porque neste caso a tela não vai ficar "travada" aos olhos do usuário.
Agora vem uma dúvida em relação a este trecho de código:
| Citação: | agora é o seguinte, o processo de pintura tem q ser executado pelo processo principal mesmo. ou seja, se vc quer q a tela não trave, vc não deve prender o processo principal.
ou seja, a thread deveria fazer o pesado e o principal atualizar a pintura, porem vc ta fazendo ao contrario. |
As instruções SQL esta sendo executado no processo principal, ou seja não estou utilizando thread para executar o SQL, eu queria saber a sua opnião, é uma boa prática utilizar thread para executar instruções SQL? tem alguma contra indicação? você utiliza thread para instruções SQL? Eu não encontrei nenhum efeito colateral que possa ocorrer, mas como conheço muito pouco sobre thread posso estar enganado.
Gostaria que se possível você me ajudasse em relação a isso.
Atenciosamente,
Pestana. _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
DonOctavioDelFlores Colaborador

Registrado: Quarta-Feira, 12 de Setembro de 2007 Mensagens: 2630 Localização: Pra lá de Bagda
|
Enviada: Ter Fev 03, 2009 10:15 am Assunto: |
|
|
pestana, o teu erro nao foi exatamente em colocar o preenchimento progressbar na thread.
O problema é que, toda vez que vc tem que atualizar o progressbar, o synchronize tem que ser usado. E quando o synchronize é usado, a thread passa a execucao para o processo principal, o que significa que a thread nao estava servindo para nada.
resumindo: não use threads que mexam com algo visual, ou com algo que está dentro do escopo do processo principal.
idealmente a thread tinha que ser um "mundo paralelo" com seus proprios recursos, e com o minimo de dependencia com recursos de fora (a progressbar).
No caso do Sql, vc pode até fazer um connection só para a thread, assim ela fica completamente independente.
Edit:
nunca cheguei a ler, mas deve ser interessante...
http://www.google.com.br/search?hl=pt-BR&q=why+threads+are+evil&btnG=Pesquisa+Google&meta=&aq=f&oq= _________________ “The problem with the world is that everyone is a few drinks behind.” Humphrey Bogart |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Ter Fev 03, 2009 10:30 pm Assunto: |
|
|
blz, agora entendi aonde esta a raiz do problema, muito obrigado gilsonnrodrigues e DonOctavioDelFlores! vocês me ajudaram muito!
DonOctavioDelFlores, vou dar uma lida com calma nos links!
Antenciosamente,
Pestana. _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
marcocunhasilva Profissional

Registrado: Segunda-Feira, 21 de Agosto de 2006 Mensagens: 740 Localização: Porto Alegre
|
Enviada: Qua Fev 04, 2009 8:35 am Assunto: |
|
|
Bom dia, amigo Pestana!
Gostaria de um favor seu... Gostaria que postasse sua solução, até para o entendimento do esclarecimento da dúvida. Tenho um documento, em português, muito interessante sobre as threads, e tem coisas que até eu mesmo desconhecia, inclusive não documentadas em livros como o Delphi 6 - Guia do Desenvolvedor. Este documento é em PDF. Se quiser, poste seu email, que eu lhe enviarei.
Abraços...
Marco Antonio |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Qua Fev 04, 2009 11:41 pm Assunto: |
|
|
| marcocunhasilva escreveu: | Bom dia, amigo Pestana!
Gostaria de um favor seu... Gostaria que postasse sua solução, até para o entendimento do esclarecimento da dúvida. Tenho um documento, em português, muito interessante sobre as threads, e tem coisas que até eu mesmo desconhecia, inclusive não documentadas em livros como o Delphi 6 - Guia do Desenvolvedor. Este documento é em PDF. Se quiser, poste seu email, que eu lhe enviarei.
Abraços...
Marco Antonio |
eu agradeceria se você enviasse esse documento pra mim [ rogerio_pestana@yahoo.com.br ]
Obrigado! _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Qua Fev 04, 2009 11:43 pm Assunto: |
|
|
Eu montei este exemplo para fins de aprendizagem, pode haver algum erro no código.
Eu agradeceria se os colegas analisassem este exemplo e desse alguma opinião em relação a isso, pode sugerir, criticar, corrigir, só não vale xingar a mãe Fiquem a vontade para dar suas opiniões, como já disse no começo eu estou aprendendo a utilizar Thread. Sua opnião vai ser muito importante pra mim!
Unit Principal:
| Código: | unit Principal;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, IBCustomDataSet, IBQuery, IBDatabase, ComCtrls, StdCtrls,
ExtCtrls, Grids, DBGrids, ThreadSQL;
type
TfrmPrincipal = class(TForm)
grdCliente: TDBGrid;
pnlInferior: TPanel;
btnPesquisar: TButton;
database: TIBDatabase;
trans: TIBTransaction;
qryCliente: TIBQuery;
dsCliente: TDataSource;
stsbarInfo: TStatusBar;
procedure btnPesquisarClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
procedure ExecutarSQL(db : TIBDataBase; transac : TIBTransaction; qry : TIBQuery);
public
{ Public declarations }
end;
var
frmPrincipal : TfrmPrincipal;
thrSQL : TThreadSQL;
implementation
{$R *.dfm}
procedure TfrmPrincipal.btnPesquisarClick(Sender: TObject);
begin
ExecutarSQL(database, trans, qryCliente);
end;
// executa a sentença SQL.
procedure TfrmPrincipal.ExecutarSQL(db : TIBDataBase; transac : TIBTransaction; qry : TIBQuery);
begin // instância objeto do tipo TThread. Esta thread é responsável por
thrSQL := TThreadSQL.Create(false, db, transac, qry); // executar sentença SQL.
end;
procedure TfrmPrincipal.FormDestroy(Sender: TObject);
begin
if thrSQL <> nil then
thrSQL := nil;
end;
end. |
Unit da thread que processa o SQL:
| Código: | unit ThreadSQL;
interface
uses Classes, SysUtils, DB, IBDataBase, IBQuery, Dialogs, ThreadProgressbar;
type
TThreadSQL = class(TThread)
private
{ Private declarations }
database : TIBDataBase;
transaction : TIBTransaction;
query : TIBQuery;
procedure Termino(Sender : TObject);
procedure ExecutarProgresso;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended : boolean; db : TIBDataBase; trans : TIBTransaction; qry : TIBQuery);
end;
var
thrProgresso : TThreadProgressbar;
implementation
constructor TThreadSQL.Create(CreateSuspended : boolean; db : TIBDataBase; trans : TIBTransaction; qry : TIBQuery);
begin
inherited Create(CreateSuspended);
database := db;
transaction := trans;
query := qry;
OnTerminate := Termino; // OnTerminate é executado quando é encerrado a thread.
FreeOnTerminate := True; // determina se a thread é destruido automaticamente.
Priority := tpHigher; // prioridade da thread em relação aos demais processos.
end;
procedure TThreadSQL.Execute;
begin
ExecutarProgresso; // cria e inicializa a thread do progressbar.
query.DisableControls;
query.Open;
query.Last;
query.EnableControls;
end;
procedure TThreadSQL.Termino(Sender : TObject);
begin // seta a propriedade Terminated para True para ser encerrado a thread.
thrProgresso.Terminate;
if thrProgresso <> nil then
thrProgresso := nil;
end;
// cria e inicializa a thread do progressbar.
procedure TThreadSQL.ExecutarProgresso;
begin
thrProgresso := TThreadProgressbar.Create(false);
end;
end. |
continua.... _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso.
Editado pela última vez por pestana em Qui Fev 05, 2009 12:02 am, num total de 5 vezes |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Qua Fev 04, 2009 11:44 pm Assunto: |
|
|
Unit da thread que processa o progressBar:
| Código: | unit ThreadProgressbar;
interface
uses Classes, ComCtrls, Controls, SysUtils;
type
TThreadProgressbar = class(TThread)
private
{ Private declarations }
procedure InicializaProgresso;
procedure PreencheProgresso;
procedure Termino(Sender : TObject);
protected
procedure Execute; override;
public
constructor Create(CreateSuspended : boolean);
end;
var
prgbarProgresso : TProgressBar;
implementation
uses Principal;
constructor TThreadProgressbar.Create(CreateSuspended : boolean);
begin
inherited Create(CreateSuspended);
OnTerminate := Termino; // OnTerminate é executado quando é encerrado a thread.
FreeOnTerminate := True; // determina se a thread é destruido automaticamente.
Priority := tpNormal; // prioridade da thread em relação aos demais processos.
Synchronize(InicializaProgresso); // inicializa o progressbar.
end;
procedure TThreadProgressbar.Termino(Sender : TObject);
begin
FreeAndNil(prgbarProgresso); // destroi e libera o progressbar.
end;
procedure TThreadProgressbar.Execute;
begin // enquanto a execução não for forçado a terminar
while not Terminated do // (atraves do evento OnTerminate da TThreadSQL).
Synchronize(PreencheProgresso); // preenche o progressbar.
end;
// inicializa o progressbar
procedure TThreadProgressbar.InicializaProgresso;
begin
prgbarProgresso := TProgressbar.Create(nil); // instância um objeto do tipo TProgressBar.
with prgbarProgresso do
begin
Parent := frmPrincipal.stsbarInfo;
Width := 122;
Height := 16;
Top := 3;
Left := 153;
Anchors := [akTop,akRight];
Position := 0;
Min := 0;
Max := 1000;
end;
end;
// preenche o progressbar.
procedure TThreadProgressbar.PreencheProgresso;
begin
with prgbarProgresso do
begin
if Position < Max then
Position := Position+1
else
Position := 0;
end;
end;
end. |
----------------
coloquei no form: dbGrid, painel, botão, statusBar e para conexão IBDataBase, IBTransaction, IBQuery e dataSource , abaixo segue a relação:
| Código: | object frmPrincipal: TfrmPrincipal
Left = 199
Top = 114
Width = 487
Height = 328
Caption = 'frmPrincipal'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object grdCliente: TDBGrid
Left = 0
Top = 0
Width = 479
Height = 234
Align = alClient
DataSource = dsCliente
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'MS Sans Serif'
TitleFont.Style = []
end
object pnlInferior: TPanel
Left = 0
Top = 234
Width = 479
Height = 41
Align = alBottom
TabOrder = 0
object btnPesquisar: TButton
Left = 8
Top = 8
Width = 75
Height = 25
Caption = 'Pesquisar'
TabOrder = 0
OnClick = btnPesquisarClick
end
end
object stsbarInfo: TStatusBar
Left = 0
Top = 275
Width = 479
Height = 19
Panels = <item>
end
object database: TIBDatabase
Connected = True
DatabaseName = 'D:\Rogerio\Informatica\Banco de dados\exemplo\DBEXEMPLO.FDB'
Params.Strings = (
'user_name=STRONG'
'password=134527'
'lc_ctype=WIN1252')
LoginPrompt = False
DefaultTransaction = trans
IdleTimer = 0
SQLDialect = 3
TraceFlags = []
Left = 88
Top = 40
end
object trans: TIBTransaction
Active = False
DefaultDatabase = database
AutoStopAction = saNone
Left = 120
Top = 40
end
object qryCliente: TIBQuery
Database = database
Transaction = trans
BufferChunks = 1000
CachedUpdates = False
SQL.Strings = (
'select * from CLIENTES')
Left = 88
Top = 72
end
object dsCliente: TDataSource
DataSet = qryCliente
Left = 120
Top = 72
end
end |
Atenciosamente,
pestana. _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Qui Fev 05, 2009 10:26 am Assunto: |
|
|
DonOctavioDelFlores e gilsonnrodrigues neste caso eu precisei utilizar o Synchronize, senão a tela trava e não aparece o progressbar sendo preenchido no statusbar, é desta forma mesmo que se faz? essa foi a única forma que encontrei para executar o SQL e preencher o progressBar e ao mesmo tempo não travar a tela . O que vocês acham deste exemplo?
Atenciosamente,
Pestana. _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
pestana Colaborador

Registrado: Sábado, 25 de Junho de 2005 Mensagens: 3147 Localização: Araras-SP
|
Enviada: Sáb Fev 07, 2009 12:32 am Assunto: |
|
|
| marcocunhasilva escreveu: | Bom dia, amigo Pestana!
Gostaria de um favor seu... Gostaria que postasse sua solução, até para o entendimento do esclarecimento da dúvida. Tenho um documento, em português, muito interessante sobre as threads, e tem coisas que até eu mesmo desconhecia, inclusive não documentadas em livros como o Delphi 6 - Guia do Desenvolvedor. Este documento é em PDF. Se quiser, poste seu email, que eu lhe enviarei.
Abraços...
Marco Antonio |
Ola Marco Antonio,
eu não recebi o arquivo, você poderia enviar novamente?
Atenciosamente,
Pestana. _________________ Ao invés de ficar desanimado no que deu de errado, olhe para frente, aprenda com os erros e veja o que ainda pode ser feito. A determinação e a persistência é uma das etapas para o sucesso. |
|
| Voltar ao Topo |
|
 |
HELDERNET Novato


Registrado: Sexta-Feira, 16 de Novembro de 2012 Mensagens: 22
|
Enviada: Ter Set 24, 2013 2:44 pm Assunto: |
|
|
| pestana escreveu: | Eu montei este exemplo para fins de aprendizagem, pode haver algum erro no código.
Eu agradeceria se os colegas analisassem este exemplo e desse alguma opinião em relação a isso, pode sugerir, criticar, corrigir, só não vale xingar a mãe Fiquem a vontade para dar suas opiniões, como já disse no começo eu estou aprendendo a utilizar Thread. Sua opnião vai ser muito importante pra mim!
|
Amigão, utilizei esse seu exemplo e me ajudou muito. Até fiz um modelo aqui e listando o resultado do ClientDataSet num dbGrid e foi tudo perfeito, porém quando troquei para o cxGrid do DevExpress, ao fechar o formulario da erro com a seguinte mensagem: Erro CODIGO 1400 - Identificador de Janela Inválido.
O que será isso ? |
|
| Voltar ao Topo |
|
 |
|
|
Enviar Mensagens Novas: Proibido. Responder Tópicos Proibido Editar Mensagens: Proibido. Excluir Mensagens: Proibido. Votar em Enquetes: Proibido.
|
|