Diese Frage ist viel komplexer als ursprünglich geplant; Das macht es zu einer guten Frage. Zunächst
Ich dachte Application.ProcessMessages der richtige Weg war, aber es ist ein potenzielles Minenfeld, wenn Sie vorsichtig sind (dank @skamradt für den Hinweis). Es hilft auch nicht mit einem einzigen blockierenden Anruf.
Ein Hintergrund-Thread wird wie folgt benötigt: (Danke @mghie für das Aufzeigen der Fehler sind jetzt gelöst). Es kann immer noch Probleme mit dem Datenbankobjekt geben, das in verschiedenen Threads aufgerufen wird. Daher muss der Hintergrundthread möglicherweise eine eigene Datenbankverbindung für diese Operation haben (falls möglich).
Im Beispiel unten ich nicht speziell den Code für die Erstellung und Zerstörung des Fortschrittsfenster gezeigt haben, wie sie den Code noch länger machen wird, und seine leicht zu tun.
Also brauchen wir zwei Objekte, dies zu tun:
Zunächst wird der Hintergrund-Thread die Abfrage zu verarbeiten.
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.
Das Formular, das die Abfrage ruft:
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.
Welche Datenbank? Mindestens eine, die ich kenne (DBISAM/ElevateDB) bietet ein sehr praktisches OnProgress-Ereignis für ihre Abfragekomponente. Sie können in ihrem Code verstrichene Zeit, Prozent abgeschlossen usw. –
kleine Anregung zu berichten: Ich würde legt den 'try' vor dem' frm.Init' – mjn
Beachten Sie, dass Aufruf 'frm.Close' in Speicherlecks, es sei denn die Form führt hat einen OnClose-Handler, der 'caFree' setzt. Mit 'frm.Release' wäre das viel sicherer. – mghie