有一个窗体form1上的Panel4放着一个gif进度条图片,默认该Panel4.Visible:=false;现在要进行多线程数据查询,当点击查询按钮时,Panel4就会显示,然后执行数据查询,将结果显示在Dbgrideh上后让Panel4隐藏,然后将查询的结果数显示在SpeedButton1上,即可。以下是我的代码,有人说可视控件不能放在多线程中(我刚运行这个代码时可以正常查询出结果,效果与预期的相同,但连续查询了几次就会报错),我是刚学多线程的,对多线程只知皮毛,想请大侠帮助改一改下面的代码,谢谢了!!!function doloop:Longint;stdcall;//执行查询核心及进度条线程函数
begin
    form1.Panel4.Visible:=true;//让进度条面板显示
    with form1.OraSession1 do
    try
        ConnectString:='ddl/[email protected]:1521:gg';
        Options.Direct:=true;
        Connected:=true;
    except
        Free;
        showmessage('系统与服务器断开连接!请与管理员联系!');
        application.Terminate;
    end;
    with form1.OraQuery1 do
    try
        Close;
        SQL.Clear;
        SQL.Add(cx_samesql);
        Prepared;
        Open;
    except
        Free;
    end;
    form1.OraQuery1.Last;
    form1.SpeedButton1.Caption:='查询(共查出 '+inttostr(form1.OraQuery1.RecordCount)+'条记录)';
    form1.OraQuery1.First;
    form1.Panel4.Visible:=false;//让进度条面板隐藏
    result:=0;
end;procedure Tform1.BitBtn1Click(Sender: TObject);//点击开始查询
begin
    hloopHandle:=CreateThread(nil,0,@doloop,nil,0,dloopThreadID);
    if hloopHandle=0 then MessageBox(Handle,'No Thread',nil,MB_OK);
    DBGridEh1.DataSource:=OraDataSource1;
end;

解决方案 »

  1.   

    线程中对VCL 控件操作 要用 TThread的Synchronize方法,Synchronize把访问VCL控件函数放到主线程中去执行 
      

  2.   

    { Important: Methods and properties of objects in VCL or CLX can only be used
      in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure aaaa.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }
      

  3.   

    哪位大侠可以写一个多线程控制VCL可视控件的简要例子吗?
      

  4.   

    现在改成这样,但还是报错,头痛啊!~
    1、线程unit:
    unit cx;
    interface
    uses
      Classes;
    type
      Tcxtheard = class(TThread)
      private
        { Private declarations }
        procedure UpdateCaption;
        procedure UpdateCaption2;
      protected
        procedure Execute; override;
      end;
    implementation
    uses main;
    procedure Tcxtheard.UpdateCaption;
    begin
        Form1.Panel1.Visible:=true;
    end;
    procedure Tcxtheard.UpdateCaption2;
    begin
        Form1.Panel1.Visible:=false;
    end;
    procedure Tcxtheard.Execute;
    begin
        Synchronize(UpdateCaption);
        with form1.OraQuery1 do
        try
            Close;
            SQL.Clear;
            SQL.Add('select * from table1');
            Prepared;
            Open;
        except
            Free;
        end;
        Synchronize(UpdateCaption2);
    end;
    end.2、主窗体代码:
    unit main;
    interface
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons, DB, DBAccess, Ora, MemDS, GifImage,
      ExtCtrls, Grids, DBGrids, GridsEh, DBGridEh;
    type
      TForm1 = class(TForm)
        OraSession1: TOraSession;
        OraQuery1: TOraQuery;
        OraDataSource1: TOraDataSource;
        SpeedButton1: TSpeedButton;
        GroupBox1: TGroupBox;
        Label1: TLabel;
        Edit1: TEdit;
        Button1: TButton;
        DBGridEh1: TDBGridEh;
        Panel1: TPanel;
        Image1: TImage;
        procedure FormShow(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    var
      Form1: TForm1;
    implementation
    uses cx;
    {$R *.dfm}
    procedure TForm1.FormShow(Sender: TObject);
    var
        i:integer;
    begin
        image1.Picture.LoadFromFile(ExtractFilePath(paramstr(0))+'load.gif');//导入进度条图像
        with OraSession1 do
        try
            ConnectString:='ddl/[email protected]:1521:gg';
            Options.Direct:=true;
            Connected:=true;
        except
            Free;
            showmessage('系统与服务器断开连接!请与管理员联系!');
            application.Terminate;
        end;
        for i:=0 to DBGridEh1.FieldCount-1 do
        begin
            DBGridEh1.Columns[i].Width:=89;
        end;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
        Thread1:Tcxtheard;
    begin
        Thread1:=Tcxtheard.Create(false);
        Thread1.FreeOnTerminate:=true;
    end;
    end.