Thread open TOracleDataSet. Crash after open (read value RecordCount). Demo app

alt0

Member
Set property on TOracleDataSet:
CountAllRecord := true;
QueryAllRecord := false;

SQL := select return big result.. "select * from all_objects union all select * from all_objects union all..."

Open DataSet on thread. And crash on read value RecordCount... though all need property is good

DataSet.Active = true
DataSet.State = dsBrowse???

Demo app. Open dataset in thread. When dataset opening... move cursor in grid... crash

Code:
--- Unit1.dfm ---
object Form1: TForm1
  Left = 324
  Top = 248
  Width = 557
  Height = 382
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object DBGrid1: TDBGrid
    Left = 0
    Top = 0
    Width = 369
    Height = 289
    DataSource = wwDataSource1
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'MS Sans Serif'
    TitleFont.Style = []
  end
  object BitBtn1: TBitBtn
    Left = 400
    Top = 224
    Width = 75
    Height = 25
    Caption = 'BitBtn1'
    TabOrder = 1
    OnClick = BitBtn1Click
  end
  object OracleSession1: TOracleSession
    LogonUsername = 'sys'
    LogonPassword = 'testtest'
    LogonDatabase = 'ASU3'
    Connected = True
    Left = 424
    Top = 24
  end
  object OracleDataSet1: TOracleDataSet
    SQL.Strings = (
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects'
      'union all'
      'select * from all_objects')
    QueryAllRecords = False
    CountAllRecords = True
    Session = OracleSession1
    Left = 424
    Top = 72
  end
  object OracleLogon1: TOracleLogon
    Left = 424
    Top = 168
  end
  object DataSource1: TDataSource
    DataSet = OracleDataSet1
    Left = 424
    Top = 120
  end
  object wwDataSource1: TwwDataSource
    DataSet = OracleDataSet1
    Left = 496
    Top = 120
  end
end
---

--- Unit1.pas ---
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Oracle, DB, OracleData, Grids, DBGrids, StdCtrls, Buttons,
  Wwdatsrc;

type
  TDOAThread = class;

  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    OracleSession1: TOracleSession;
    OracleDataSet1: TOracleDataSet;
    OracleLogon1: TOracleLogon;
    DataSource1: TDataSource;
    BitBtn1: TBitBtn;
    wwDataSource1: TwwDataSource;
    procedure BitBtn1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    pDOAThread : TDOAThread;
  public
    { Public declarations }
  end;

  TDOAThreadType = ( ttOpen, ttRefresh, ttRefreshRecord, ttExecSQL, ttExecQBE );

  TDOAThread = class( TThread )
  private
    m_pDataSet   : TOracleDataSet;
    m_bBreaked   : Boolean;
    m_bCanceled  : Boolean;
    m_pException : TObject;
    m_ThreadType : TDOAThreadType;
    m_pForm : TForm;
    procedure   ClearException;
    procedure   ThreadStop;
    procedure   ThreadBreak;
  protected
    procedure   Execute; override;
    procedure   Terminate; reintroduce;
    property    Breaked : Boolean read m_bBreaked;
    property    Canceled : Boolean read m_bCanceled;
    property    Exception : TObject read m_pException;
  public
    constructor Create( Form : TForm );
    destructor  Destroy; override;
    procedure   Run( DataSet : OracleData.TOracleDataSet; ThreadType : TDOAThreadType ); overload;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TDOAThread.Create( Form : TForm );
begin
  inherited Create( true );
  FreeOnTerminate := False;
  Priority := tpIdle;
  m_pForm := Form;
  m_bCanceled := false;
  m_bBreaked := false;
  m_pDataSet := nil;
  m_pException := nil;
end;

procedure TDOAThread.Execute;
begin
  repeat
    ClearException;
    m_bBreaked := false;
    m_bCanceled := false;
    try
      case ( m_ThreadType ) of
        ttOpen          : m_pDataSet.Open;
        ttRefresh       : m_pDataSet.Refresh;
        ttRefreshRecord : m_pDataSet.RefreshRecord;
        ttExecSQL       : m_pDataSet.ExecSQL;
        ttExecQBE       : m_pDataSet.ExecuteQBE;
      end;
      ReturnValue := 0;
    except
      m_bBreaked := true;
      m_pException := AcquireExceptionObject;
      if ( m_pException is EOracleError ) then
        m_bCanceled := (( m_pException as EOracleError ).ErrorCode = 1013 );
      ReturnValue := -1;
    end;
    Synchronize( ThreadStop );
    m_pDataSet := nil;
    if ( not Terminated ) then
      Suspended := true;
  until ( Terminated );
end;

procedure TDOAThread.Run( DataSet : TOracleDataSet; ThreadType : TDOAThreadType );
begin
  m_pDataSet := DataSet;
  m_ThreadType := ThreadType;
  inherited Resume;
end;

procedure TDOAThread.ThreadBreak;
begin
  if ( assigned( m_pDataSet )) then
    m_pDataSet.Session.BreakExecution;
end;

procedure TDOAThread.Terminate;
begin
  ThreadBreak;
  inherited;
end;

destructor TDOAThread.Destroy;
begin
  Terminate;
  inherited;
  ClearException;
end;

procedure TDOAThread.ClearException;
begin
  if ( assigned( m_pException )) then
    FreeAndNil( m_pException );
end;

procedure TDOAThread.ThreadStop;
begin
  m_pForm.Caption := 'Ok';
end;

{ TForm1 }

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  pDOAThread.Run( OracleDataSet1, ttOpen );
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  pDOAThread := TDOAThread.Create( Self );
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil( pDOAThread );
end;

end.
Need help!!!
 
>You cannot open a dataset in a background thread while connected to data-aware controls
PL/SQL Developer open dataset in thread. Grid fill on fetching query. Me need liked function... only with set property CountAllRecord := true

I reed forum before... and see canceldataset.zip demo project...
in AfterFetchRecord exec RecordCount... in main thread! app freeze on first exec...

Code:
function TOracleDataset.GetRecordCount: Longint;
...
    if not Counted then
    begin
      RowCount := [b]CountQueryHits;[b]
      Counted := True;
    end;
....
modify thread override execute procedure

Code:
var
  bCountAllRecords : Boolean;
...
          bCountAllRecords := m_pDataSet.CountAllRecords;
          m_pDataSet.CountAllRecords := false;
          case ( m_ThreadType ) of
            ttOpen          : m_pDataSet.Open;
            ttRefresh       : m_pDataSet.Refresh;
            ttRefreshRecord : m_pDataSet.RefreshRecord;
            ttExecSQL       : m_pDataSet.ExecSQL;
            ttExecQBE       : m_pDataSet.ExecuteQBE;
          end;
          m_pDataSet.DisableControls;
          try
            m_pDataSet.CountAllRecords := bCountAllRecords;
            m_pDataSet.RecordCount;
          finally
            m_pDataSet.EnableControls;
          end;
this avoid crash on exec RecordCount in main ;(
 
PL/SQL Developer open dataset in thread. Grid fill on fetching query. Me need liked function.
PL/SQL Developer does not use a TOracleDataSet. It uses a TOracleQuery that fills a grid in controlled and threadsafe mode.
 
Back
Top