Hallo,
mein 1. Versuch, den Querypart in einem
Thread laufen zu lassen, um bei langen Abfragen
1. die Abfrage beenden zu können und
2. "die Anwendung reagiert nicht mehr" zu vermeiden.
Das ganze läuft mit IBObjects Komponenten und das Ergebnis wird in einem cxGrid angezeigt.
DB -> TiboDatabase -> TiboTransaction -> TiboQuery -> TDataSource -> TcxGridDBTableView
Es funktioniert alles ohne Probleme. Nur beim Programmende gibt immer Fehler 1400 "Ungültiges Fensterhandle", wenn vorher eine
Query über den
Thread gelaufen ist.
Bleibt möglicherweise die Verbindung "FQuery := aQuery", nach dem der
Thread weg ist, bestehen und zeigt ins Nirvana?
Code:
type
TiboqThread = class( TThread )
private
FQuery : TiboQuery;
FErrorCode : integer;
FErrorText : string;
public
constructor Create( AQuery : TiboQuery );
destructor Destroy; override;
procedure Execute; override;
procedure ClearError;
procedure SendError;
end; { type }
constructor TiboQThread.Create( aQuery : TiboQuery );
begin
inherited Create( True );
FQuery := aQuery;
end;
procedure TiboQThread.ClearError;
begin
LastErrCode := 0;
LastErrText := '';
end;
procedure TiboQThread.SendError;
begin
LastErrCode := FErrorCode;
LastErrText := FErrorText;
end;
procedure TiboQThread.Execute;
var i : integer;
begin
inherited;
try
Synchronize( ClearError );
FQuery.Open;
except
on E :
Exception do begin
FErrorCode := 4313; // ERROR_DATABASE_FAILURE;
FErrorText := '
Query-Thread:' + E.ClassName + ' - ' + E.Message;
Synchronize( SendError );
end;
end;
end;
destructor TiboQThread.Destroy;
begin
FQuery := nil;
inherited;
end;
// Main
// ...
IBQ1.Active := False;
IBQ1.SQL.Text := tmpSql;
// IBQ1.Active := True;
// Try it via
Thread
tQ := TiboqThread.create( IBQ1 );
tQ.FreeOnTerminate := False;
tQ.Resume;
while ( WaitForSingleObject( tQ.Handle, 100 ) = WAIT_TIMEOUT ) and
( A_Halt.Tag = 0 )
do begin
Application.ProcessMessages;
end;
if LastErrCode = 0 then begin
// Alles OK
end else begin
FehlerAusgabe1( LastErrText );
end;
tQ.Free;
// ...
Ausschnitt aus dem Bugreport
Code:
exception class : EOSError
exception message : System Error. Code: 1400. Ungültiges Fensterhandle.
main
thread ($8b0):
0045ff80 +070 TEST.exe SysUtils RaiseLastOSError
0045ff09 +005 TEST.exe SysUtils RaiseLastOSError
004bb551 +031 TEST.exe Controls TWinControl.DestroyWindowHandle
004b9e0b +05f TEST.exe Controls TWinControl.Destroy
004c0ba5 +01d TEST.exe Controls TCustomControl.Destroy
0054b8e4 +020 TEST.exe cxControls 1987 +2 TcxSizeGrip.Destroy
00404710 +008 TEST.exe System 48 +0 TObject.Free
00460630 +008 TEST.exe SysUtils FreeAndNil
0054c60d +021 TEST.exe cxControls 2507 +5 TcxControl.DestroyScrollBars
0054bc65 +019 TEST.exe cxControls 2127 +2 TcxControl.Destroy
0070423c +01c TEST.exe cxGridCustomView 4296 +3 TcxGridSite.Destroy
00404710 +008 TEST.exe System 48 +0 TObject.Free
00460630 +008 TEST.exe SysUtils FreeAndNil
00706c6e +006 TEST.exe cxGridCustomView 6071 +1 TcxCustomGridViewInfo.DestroySite
00706a4c +010 TEST.exe cxGridCustomView 5975 +1 TcxCustomGridViewInfo.Destroy
006f2b24 +020 TEST.exe cxGridCustomTableView 12424 +2 TcxCustomGridTableViewInfo.Destroy
Erfahrung ist etwas, daß man erst bekommt, kurz nachdem man es dringend gebraucht hätte.