How to show elapsed time when a long SQL query is executed?

I need to show a pop-up window before executing the query, show the elapsed time during the execution of the sql query , and close this window when the query completes.

I'm actually doing something like this

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; 

How to update a label to show elapsed time during query execution? Using a timer? Or a thread?

+6
delphi delphi-7
source share
3 answers

You need to execute the request asynchronously , which will allow you to update the form in the meantime.
The easiest way to do this without clogging your hands with threads is to use the Andreas Hausladen AsynCalls Library > .
You can also check out the OmniThread Library from Primoz Gabrijelcic.

+4
source share

You will need to run the request in the background thread if you want the user interface to respond during the execution of the request. If the request supports cancellation, you can also add a cancel button. I believe that only ADO requests support this.

+1
source share

This question is much more complicated than originally thought; which makes him a good question.

Initially, I thought Application.processmessages was correct, but this is a potential minefield if you are not careful (thanks @skamradt for pointing this out). It also does not help with one blocking call.

A background thread is needed as follows: (thanks @mghie for pointing out the bugs that are now resolved). There may still be problems with calling the database object in different threads, so the background thread may need its own connection to the database for this operation (if this is practically possible).

In the example below, I did not specifically show the code for creating and destroying the execution window, as it will make the code even longer and easy to make.

To do this, we need two objects:

Firstly, a background thread to process the request.

 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. 

The form that invokes the request:

 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. 
0
source share

All Articles