Einzelnen Beitrag anzeigen

Benutzerbild von cramer
cramer

Registriert seit: 23. Jun 2004
Ort: Velbert (NRW)
96 Beiträge
 
Delphi 2006 Enterprise
 
#1

Thread Query keep it simple ABER ...

  Alt 8. Apr 2015, 19:41
Delphi-Version: 2006
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.
  Mit Zitat antworten Zitat