我在一个按钮的单击事件里调用了一个SQL的存储过程,该过程在查询分析器执行大概需要10分钟左右,我就想当我点击执行后,我的程序出现一个循环滚动的进度条,等执行完后进度条消失。经过测试,单独让进度条循环滚动是OK的,当开始执行过程后,再去让进度条滚动就效果了,整个界面就是死机一样,什么都动不了,请问有什么好的办法可以做到这个效果?

解决方案 »

  1.   

    那是,主线程在等待SQL执行结果,当然界面就像死了一样没反应了,另外开个线程来显示进度就没问题
      

  2.   

    那到底是主线程序处理SQL好,还是子线程处理SQL好一些呢?
      

  3.   

    看情况,如果说你程序要等到SQL执行完了才能有后续操作,那还是主线程处理SQL,子线程处理进度条
      

  4.   

    我认为相反,如果子线程处理VCL可能有问题,而且当时几乎无法响应消息,连最小化也不行,会引起用户误解。
      

  5.   

    注意啊,说的是看情况,到子线程去处理SQL,到时候会复杂
      

  6.   

    创建子线程来后台处理SQL,主线程才可以继续响应用户操作
      

  7.   

    我这样写好象是有问题,请大家给点意见:(主线程处理进度条,子线程处理SQL过程)
      
    启动执行SQL过程按钮事件:
    begin
      timer1.Enabled:=true; //利用一个timer来循环显示滚动条
      //启动线程
      Try
        MyPG.Create(false);
      Except
      end;
    end//线程的代码如下:unit MyPGThr;interfaceuses
      Classes;type
      MyPg = class(TThread)
      private
        { Private declarations }
      protected
        constructor Create;
        procedure Execute; override;
     
        procedure p_ExecSQL();
      end;implementationuses Unit1, Unit2; constructor MyPg.Create;
    begin
      inherited create(false); //启动线程
     
    end;procedure MyPg.Execute;
    begin
     {Place thread code here }
     
      Synchronize(p_ExecSQL);end;procedure MyPg.p_ExecSQL(); //执行SQL语句 
    begin
      with Form1 do
      begin
        aq.close;
        aq.SQL.Text:='exec P_MyProc 1';
        Try
          aq.ExecSQL;
        Except
        end;
      end;
    end;end.
    一执行就像死机一样,没有反应。
      

  8.   

    开两个子线程,一个处理进度条,一个处理SQL,主线程正常执行,响应用户其它操作。
      

  9.   

    http://topic.csdn.net/u/20100809/00/e0a77b3e-615e-4027-8386-4d3e5a839978.html
      

  10.   

    TADOCommand 的 Help 已經說明TADOCommand is most often used for executing data definition language (DDL) SQL commands or to execute a stored procedure that does not return a result set. For SQL statements that return a result set, TADODataSet, TADOQuery, or TADOStoredProc is better suited.
      

  11.   

    子线程画一个进度条的等待窗,直接用VCL的东西的话没用,主线程卡住了子线程一样不显示。。
      

  12.   

    我也遇到过这种问题,我做了2个公用的线程其中一个的做法是新建了一个窗体,放一个滚动条,和2个TIMER,当主窗体进行长时间数据操作时,调用此窗体,不过为了引起冲突等问题,我把这个窗体showmodel出来后,就不允许进行其他操作,只不过让用户知道,程序没有死机而已。
    其中一个滚动滚动条,另一个监测数据操作是否完成,完成时注销线程。Constructor TCheckServerThread.Create(AQuery: TADOQuery; Var ASqlStr: String);
    Begin
      Inherited Create(True);
      FDateSet := AQuery;
      FProSqlStr := ASqlStr;
      //
    End;Destructor TCheckServerThread.Destroy;
    Begin
      //
      Inherited;
    End;Procedure TCheckServerThread.Execute;
    Var
      AI: Integer;
    Begin
      Inherited;
      FDateSet.SQL.Text := FProSqlStr;
      Try
        FDateSet.ExecSQL;                      //长时间的SQL操作
        PubFrm.FEexComPleate := '1';          //初始值为0,公用变量,记录在一个UNIT里,SQL操作完成后,根据这个数值停止线程
      Except
        PubFrm.FEexComPleate := '2';
      End;
    End;
    调用时:
    Function TFrm_ProcThread.ExcuteProc(ASqlStr: String): Boolean;
    Begin
      Label8.Visible := true;
      tmr1.Enabled := true;
      Timer1.Enabled := true;
      FEexComPleate := '0';
      FCheckServerThread := TCheckServerThread.Create(qry_temp, ASqlStr);
      FCheckServerThread.Resume;
    End;Procedure TFrm_ProcThread.tmr1Timer(Sender: TObject);
    Begin
      Inherited;
      //,处理滚动事件,我原来为了好看,自己画了个图片,用TMR1不停的滚动
      self.Refresh;
    End;Procedure TFrm_ProcThread.Timer1Timer(Sender: TObject);
    Var
      SQLStr: String;
    Begin
      Inherited;
      If PubFrm.FEexComPleate <> '0' Then
        Begin
          //线程注销 ,同时停止Timer等的操作    End;
    End;