ActiveDelphi - Índice do Fórum ActiveDelphi
.: O site do programador Delphi! :.
 
 FAQFAQ   PesquisarPesquisar   MembrosMembros   GruposGrupos   RegistrarRegistrar 
 PerfilPerfil   Entrar e ver Mensagens ParticularesEntrar e ver Mensagens Particulares   EntrarEntrar 

Thread com CxGrid: gerando erro cod 1400 (RESOLVIDO)

 
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi
Exibir mensagem anterior :: Exibir próxima mensagem  
Autor Mensagem
HELDERNET
Novato
Novato


Registrado: Sexta-Feira, 16 de Novembro de 2012
Mensagens: 22

MensagemEnviada: Qui Set 26, 2013 4:39 pm    Assunto: Thread com CxGrid: gerando erro cod 1400 (RESOLVIDO) Responder com Citação

Olá Pessoal !!

O sistema que trabalho, carrega vários grids na tela principal e isso as vezes demora quase um minuto e nesse intervalo, quando ele tenta abrir um dataset a janela trava, mas depois que termina carregar os dados ela volta. Mas para o cliente isso e muito chato, pois dá impressão que todo o sistema está travado.

Então, para melhorar isso coloquei o dataset pra ser carregado por uma Thread e a aplicação principal atualizando a tela e um ProgressBar em movimento. Até então, deu quase tudo certo, sendo que o problema é ao finalizar o sistema dá o seguinte erro: SYSTEM ERROR: CODE 1400. O IDENTIFICADOR DA JANELA E INVÁLIDO.

Baseado num modelo que achei em um forum aqui nesse site:
http://www.activedelphi.com.br/forum/viewtopic.php?p=243894

Fiz um modelo semelhante ao sistema do projeto que trabalho e nesse modelo coloquei um DBGrid e um CxGrid(DevExpress), quando o DataSet gera os dados no DBGrid NAÃO Gera o erro, mas quando gero o dataset conectado ao CxGrid, aparece o erro ao finalizar o sistema.

Alguém pelo amor de Deus, me ajuda !!

vou colocar o código do sistema aqui e o link do codigo do projeto ja pronto junto com o scritp que gera uma tabela de exemplo:


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, cxGraphics, cxControls,
  cxLookAndFeels, cxLookAndFeelPainters, cxStyles, cxCustomData, cxFilter,
  cxData, cxDataStorage, cxEdit, cxDBData, cxGridCustomTableView,
  cxGridTableView, cxGridDBTableView, cxGridLevel, cxClasses,
  cxGridCustomView, cxGrid, Provider, DBClient, ADODB;
type
  TfrmPrincipal = class(TForm)
    Button1: TButton;
    stsbarInfo: TStatusBar;
    ADOConnection1: TADOConnection;
    qryteste: TADOQuery;
    cds: TClientDataSet;
    dspteste: TDataSetProvider;
    dsteste: TDataSource;
    DBGrid: TDBGrid;
    cxGridDBTableView1: TcxGridDBTableView;
    cxGridLevel1: TcxGridLevel;
    cxGrid: TcxGrid;
    Button3: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button3Click(Sender: TObject);
  private
     procedure ExecutarSQL;
    { Private declarations }
  public
    { Public declarations }
  end;

var
   frmPrincipal: TfrmPrincipal;
   thrSQL : TThreadSQL;
   Terminou : Boolean;

implementation

{$R *.dfm}

procedure TfrmPrincipal.Button1Click(Sender: TObject);
begin
 cds.Close;

 cxGridDBTableView1.DataController.DataSource := nil;
 DBGrid.DataSource := dsteste;

 ExecutarSQL;

 ShowMessage('Dados carregados com sucesso!' + #13 +
             'O sistema será finalizado e NÃO irá gerar o erro');

 Application.Terminate;
end;


procedure TfrmPrincipal.Button3Click(Sender: TObject);
begin
 cds.Close;

 DBGrid.DataSource := nil;

 cxGridDBTableView1.DataController.DataSource := dsteste;

 ExecutarSQL;

 ShowMessage('Dados carregados com sucesso!' + #13 +
             'O sistema será finalizado e irá gerar o erro do COD 1400.');

 Application.Terminate;

end;

procedure TfrmPrincipal.ExecutarSQL;
begin  // instância objeto do tipo TThread.  Esta thread é responsável por
   Terminou := False;

   thrSQL := TThreadSQL.Create(False, cds);  // executar sentença SQL.

   {segura a aplicação até carregar todo o dataset}
   while not Terminou  do
     Application.ProcessMessages;

   thrSQL := nil;
end;


procedure TfrmPrincipal.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  action := Cafree;
end;

procedure TfrmPrincipal.FormDestroy(Sender: TObject);
begin
  if thrSQL <> nil then
     thrSQL := nil;
end;

end.




UNIT THREAD

Código:

unit ThreadSQL;

interface

uses Classes, SysUtils, ADODB, ComCtrls, DBClient, IBQuery, Dialogs, Controls;

type
  TThreadSQL = class(TThread)
  private
    { Private declarations }
    cds : TClientDataSet;
    procedure Termino(Sender : TObject);
    procedure ExecutarProgresso;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended : boolean; pcds : TClientDataSet);
  end;

  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
   thrProgresso : TThreadProgressbar;
   prgbarProgresso : TProgressBar;

implementation

uses Principal;

constructor TThreadSQL.Create(CreateSuspended : boolean; pcds : TClientDataSet);
begin
   inherited Create(CreateSuspended);

   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.
   cds := pcds;
end;

procedure TThreadSQL.Execute;
var
  j: Integer;
begin
   ExecutarProgresso;        // cria e inicializa a thread do progressbar.
   cds.DisableControls;
   cds.Open;
   cds.Last;
   cds.EnableControls;

   Terminou := True;


   Self.Terminate;

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;


{TThreadProgressbar}
             
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 := alClient;
       align := alClient;
       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;

         {coloca o progressbar mais lento}
         sleep(10);
    end;
end;


end.




Aqui estou utilizando o Delphi 2007 e o Banco de Dados SQLSERVER 2008.

-Baixe o codigo fonte no link postado:
Citação:
https://mega.co.nz/#!mY9A1CgT!RBuyfGJLBKWjuRizJnGRw3x4kX4cLiA3onjqRktLeiE

-Crie um banco de dados com nome DBDEMO ou como desejar
-Abra o arquivo txt e gere o script do sql para gerar a tabela modelo e inserir os dados ou restaura o backup que está junto caso sua versão do sqlserver seja 2008.
-No formulario principal, configure a conexão com o ADOCONNECTION
-Executa a aplicação

Observe, quando vc gera o sistema clicando no botão gerar no DBGRID, ele gera e carrega o grid normal, e ao fechar nao dá erro, mas quado vc gera clicando no botão para gerar no CxGrid, da o erro CODE 1400 e não sei o que pode ser.

Agradeço a ajuda e a atençao de todos.

vlw


Editado pela última vez por HELDERNET em Ter Dez 03, 2013 9:13 am, num total de 1 vez
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
HELDERNET
Novato
Novato


Registrado: Sexta-Feira, 16 de Novembro de 2012
Mensagens: 22

MensagemEnviada: Sex Set 27, 2013 9:26 am    Assunto: Re: Thread com CxGrid: gerando erro cod 1400 Identif. Inválido. Responder com Citação

Curiosidade:

Peguei um banco de dados *.mdb (access), e conectei nesse modelo que fiz aqui. Abriu as tabelas no CxGrid e ao fechar não gerou o erro. Mas com o banco SQL Server que estou usando, dá o erro. Pq será ?
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
HELDERNET
Novato
Novato


Registrado: Sexta-Feira, 16 de Novembro de 2012
Mensagens: 22

MensagemEnviada: Sex Out 18, 2013 4:17 pm    Assunto: Re: Thread com CxGrid: gerando erro cod 1400 Identif. Inválido. Responder com Citação

Pessoal, estou passando por aqui só pra dizer que consegui resolver.

SOLUÇÃO: Antes de fazer a chamada da Thread, peguei todos os eventos do ClientDataSet e do DasaSet do cxgrid, atribui nil a eles, chamei a thread passando o Clientdataset no parametro e depois que terminou, voltei os eventos e o vínculo do grid. Funcionou.

EXEMPLO

cxgrid.DataController.DataSource := nil;
cdsForm.AfterScroll := nil;

{thread}
AbrirCDSTh(cdsForm);

cxgrid.DataController.DataSource := dsForm;
cdsForm.AfterScroll := cdsformAfterScroll;
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
TheBlueMonkey
Novato
Novato


Registrado: Sexta-Feira, 28 de Dezembro de 2012
Mensagens: 32

MensagemEnviada: Sex Nov 08, 2013 11:43 am    Assunto: Re: Thread com CxGrid: gerando erro cod 1400 Identif. Inválido. Responder com Citação

HELDERNET escreveu:
Pessoal, estou passando por aqui só pra dizer que consegui resolver.

SOLUÇÃO: Antes de fazer a chamada da Thread, peguei todos os eventos do ClientDataSet e do DasaSet do cxgrid, atribui nil a eles, chamei a thread passando o Clientdataset no parametro e depois que terminou, voltei os eventos e o vínculo do grid. Funcionou.

EXEMPLO

cxgrid.DataController.DataSource := nil;
cdsForm.AfterScroll := nil;

{thread}
AbrirCDSTh(cdsForm);

cxgrid.DataController.DataSource := dsForm;
cdsForm.AfterScroll := cdsformAfterScroll;


Heldernet, cara. Quero muito te agradecer por ter postado a solução mesmo sem que ninguém tenha respondido o tópico. Eu estava com um problema meio parecido (Access Violation ao abrir de dentro de uma thread uma query vinculada a um CxGrid) e a tua solução apesar de simples foi bastante eficiente e de grande ajuda, já havia passado toda a tarde anterior apanhando com este probema.

Obrigado com compartilhar a tua solução.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
HELDERNET
Novato
Novato


Registrado: Sexta-Feira, 16 de Novembro de 2012
Mensagens: 22

MensagemEnviada: Ter Dez 03, 2013 9:16 am    Assunto: Re: Thread com CxGrid: gerando erro cod 1400 Identif. Inválido. Responder com Citação

TheBlueMonkey escreveu:
Obrigado com compartilhar a tua solução.


Fico feliz em ter contribuído para a solução do seu problema.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Mostrar os tópicos anteriores:   
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi Todos os horários são GMT - 3 Horas
Página 1 de 1

 
Ir para:  
Enviar Mensagens Novas: Proibido.
Responder Tópicos Proibido
Editar Mensagens: Proibido.
Excluir Mensagens: Proibido.
Votar em Enquetes: Proibido.


Powered by phpBB © 2001, 2005 phpBB Group
Traduzido por: Suporte phpBB