Search code examples
multithreadingdelphiado

Delphi catch Async ADOQuery Exception


I am opening an ADOQuery asynchronously, and it works as expected, but any exceptions cause the application to hang. The exception does not get passed back to the main thread.

procedure TfrmMain.actRunExecute(Sender: TObject);
begin
  ReportOpening := true;
  with myADOQuery do begin
    ExecuteOptions := [eoAsyncExecute, eoAsyncFetch, eoAsyncFetchNonBlocking];
    OnFetchProgress := ADOQueryFetchProgress;
    OnFetchComplete := ADOQueryFetchComplete;
    try
		Open;
    except
		on E: Exception do MessageDlg(E.Message, mtError, [mbOK], 0); //I expect a timeout here
    end;
  end;
end;

procedure TfrmMain.ADOQueryFetchComplete(DataSet: TCustomADODataSet; const Error: Error; var EventStatus: TEventStatus);
begin
  ReportOpening := false;
end;

procedure TfrmMain.ADOQueryFetchProgress(DataSet: TCustomADODataSet; Progress, MaxProgress: Integer; var EventStatus: TEventStatus);
begin
  TThread.Synchronize(nil, procedure()
	begin
		StatusBar1.Panels[1].Text := Format('Progress: %d of %d',[Progress, MaxProgress]);
    end;
    );
  Application.ProcessMessages;
end;


Solution

  • In async mode, you can catch the error in the OnExecuteComplete event handler of your TADOConnection object. You can use the EventStatus and Error objects to determine if there was a problem. Error.Description will give you the error returned by the database server.

    P.S.: please refrain from using Application.ProcessMessages in your code as it is not needed since you are using async queries and it can lead to unforeseen event reentry scenarios.

    Example:

    procedure TForm1.ADOConnection1ExecuteComplete(Connection: TADOConnection; RecordsAffected: Integer; const Error: Error;
                                                   var EventStatus: TEventStatus; const Command: _Command; const Recordset: _Recordset);
    begin
     if EventStatus = esErrorsOccured then
      begin
       memo1.Lines.add(Error.Description);
       // recover from error here
      end;
    end;