如何在执行长SQL查询时显示已用时间?

时间:2010-03-26 21:11:18

标签: delphi delphi-7

我需要在执行查询之前显示一个弹出窗口,显示执行sql查询时经过的时间,并在查询结束时关闭该窗口。

其实我这样做

var
  frm : tFrmPopupElapsed;
  // this form has a TTimer and a TLabel to show the elapsed time
  // but the label is not updated, I tried using update and refresh
  // but nothing happens
begin
  frm := tFrmPopupElapsed.Create(nil);
  try
    frm.Init; // this procedure enables the timer
    frm.Show();
    ExecuteMyVeryLongQuery();
  finally
    frm.Close; 
  end;
end;

如何更新标签以显示查询执行时的已用时间?使用计时器?还是线程?

3 个答案:

答案 0 :(得分:4)

您需要运行查询异步,允许您在此期间更新表单。
最简单的方法就是使用线程来解决问题的方法是使用Andreas Hausladen的AsynCalls library。 您还可以查看Primoz Gabrijelcic的 OmniThread Library

答案 1 :(得分:1)

如果希望用户界面在查询执行期间响应,则需要在后台线程中运行查询。如果查询支持取消,您还可以添加取消按钮。不过,我相信只有ADO查询支持这一点。

答案 2 :(得分:0)

这个问题比最初设想的要复杂得多;这使它成为一个很好的问题。

最初我认为Application.processmessages是正确的方法,但是除非你小心,否则它是一个潜在的雷区(感谢@skamradt指出这一点)。它对单个阻塞调用也无济于事。

需要后台线程如下:(感谢@mghie指出错误 现在已经解决)。在不同的线程中调用数据库对象可能仍然存在问题 - 因此后台线程可能需要为此操作拥有自己的数据库连接(如果可行)。

在下面的示例中,我没有具体显示创建和销毁进度窗口的代码,因为它会使代码更长,并且更容易实现。

所以我们需要两个对象来做到这一点:

首先是处理查询的后台线程。

unit BackgroundProcess;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs, windows;

const
  WM_MY_BACKGROUNDNOTIFY = WM_USER + 555; { change this }
  NOTIFY_BEGIN = 22;
  NOTIFY_END   = 33;

type
  TBackgroundQueryThread = class(TThread)
  private
    hwndnotify : HWND;
  protected
    procedure Execute; override;
  public
    constructor Create(owner: TForm);
  end;


implementation

constructor TBackgroundQueryThread.Create(owner: TForm) ;
begin
    inherited Create(False);
    hwndnotify := owner.Handle;
    FreeOnTerminate := true;
    resume;
end;

procedure TBackgroundQueryThread.Execute;
begin
     PostMessage(hwndnotify, WM_MY_BACKGROUNDNOTIFY, NOTIFY_BEGIN, 0);
     Sleep(2000); (* Query goes here. *)
     PostMessage(hwndnotify, WM_MY_BACKGROUNDNOTIFY, NOTIFY_END, 0);
end;

end.           

调用查询的表单:

unit mainform;

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls, ExtCtrls, windows, BackgroundProcess;

type
  TForm1 = class(TForm)
  private
    frm : tFrmPopupElapsed;
    { private declarations }
    procedure OnMyBackgrounNotify(var Msg: TMessage); message WM_MY_BACKGROUNDNOTIFY;
  public
    { public declarations }
  end; 

var
  Form1: TForm1; 

implementation


procedure TForm1.OnMyBackgrounNotify(var Msg: TMessage);
begin
  if (msg.WParam = NOTIFY_BEGIN) THEN
  BEGIN
     if (frm = nil) THEN
     BEGIN
         frm := tFrmPopupElapsed.Create(nil);
         frm.Init; // this procedure enables the timer
         frm.Show();
     END;
  END;

  if (msg.WParam = NOTIFY_END) THEN
  BEGIN
     if (frm <> nil) THEN
     BEGIN
         frm.Close;
     END;
  END;

end;

end.