Subject | AV when switching to another app |
---|---|
Author | Toby Leonard |
Post date | 2005-05-06T16:59:56Z |
I've been having some issues with profiling (using AQtime) an app that uses
the Unified Interbase components, and figured I'd give IBO a try. The test
system is XPSP2, D2005 Update 1, IBO Eval 4.5, and FB embedded 1.5.2.4731.
I can run the code below in the IDE or standalone, and as long as I leave it
focused until I close it, it performs as expected. However if I switch to
another app while the main processing is going on or after I've stopped it,
the app AVs at 00000000 trying to read 00000000. Under AQtime I get the AV
regardless.
Testing this, it looks like I can have as little as the TIB_Session created in
the thread, and the AV occurs.
(Yeah I know some of the stuff in here is bad coding practice, like the A.PM
and Sleep(1) combo. I wouldn't normally do such things - this is just a
throwaway test app.)
Any help would be greatly appreciated. Thanks!
unit Unit22;
interface
uses
Forms, Controls, StdCtrls, Classes, ExtCtrls;
type
TForm22 = class(TForm)
Panel1: TPanel;
Button1: TButton;
LB: TListBox;
procedure Button1Click(Sender: TObject);
end;
var
Form22: TForm22;
implementation
{$R *.dfm}
uses
Windows, SysUtils, IB_Components, SyncObjs;
const
MAX_THREADS = 10;
type
TIBTestThread = class(TThread)
private
FDBSession: TIB_Session;
FDBConnection: TIB_Connection;
FDBTransaction: TIB_Transaction;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
var
KeepGoing: Boolean;
TotalThreads: Cardinal;
CS: TCriticalSection;
constructor TIBTestThread.Create;
begin
inherited Create(False);
FreeOnTerminate := True;
FDBSession := TIB_Session.Create(nil);
FDBConnection := TIB_Connection.Create(FDBSession);
FDBConnection.IB_Session := FDBSession;
FDBConnection.Path := ExtractFilePath(ParamStr(0)) + 'foo.fdb';
FDBConnection.Username := 'foo';
FDBConnection.Password := 'bar';
FDBConnection.Connect;
FDBTransaction := TIB_Transaction.Create(FDBSession);
FDBTransaction.IB_Connection := FDBConnection;
end;
destructor TIBTestThread.Destroy;
begin
CS.Enter;
try
Dec(TotalThreads);
finally
CS.Leave;
end;
FDBTransaction.Free;
FDBConnection.Disconnect;
FDBConnection.Free;
FDBSession.Free;
inherited;
end;
procedure TIBTestThread.Execute;
var
Cursor: TIB_Cursor;
begin
Cursor := TIB_Cursor.Create(FDBSession);
try
Cursor.IB_Transaction := FDBTransaction;
Cursor.SQL.Text :=
'select ' +
' RDB$RELATION_NAME ' +
'from ' +
' RDB$RELATIONS';
Cursor.Open;
try
while not Cursor.Eof do
begin
Cursor.Next;
end;
finally
Cursor.Close;
end;
finally
Cursor.Free;
end;
Terminate;
end;
procedure TForm22.Button1Click(Sender: TObject);
var
StillThreads: Boolean;
begin
try
if Button1.Caption <> 'Go' then
begin
KeepGoing := False;
Exit;
end;
Button1.Caption := 'Stop';
try
CS := TCriticalSection.Create;
try
Button1.Enabled := False;
try
TotalThreads := 0;
KeepGoing := True;
finally
Button1.Enabled := True;
end;
while KeepGoing do
begin
CS.Enter;
try
if TotalThreads < MAX_THREADS then
begin
TIBTestThread.Create;
Inc(TotalThreads);
end;
finally
CS.Leave;
end;
Application.ProcessMessages;
Sleep(1);
end;
Button1.Enabled := False;
try
repeat
CS.Enter;
try
StillThreads := TotalThreads > 0;
finally
CS.Leave;
end;
Application.ProcessMessages;
Sleep(1);
until not StillThreads;
finally
Button1.Enabled := True;
end;
finally
CS.Free;
end;
finally
Button1.Caption := 'Go';
end;
except
on E:Exception do
begin
OutputDebugString(PChar('EXCEPTION - ' + E.ClassType.ClassName + ' - ' +
E.Message));
end;
end;
end;
end.
--
Toby
the Unified Interbase components, and figured I'd give IBO a try. The test
system is XPSP2, D2005 Update 1, IBO Eval 4.5, and FB embedded 1.5.2.4731.
I can run the code below in the IDE or standalone, and as long as I leave it
focused until I close it, it performs as expected. However if I switch to
another app while the main processing is going on or after I've stopped it,
the app AVs at 00000000 trying to read 00000000. Under AQtime I get the AV
regardless.
Testing this, it looks like I can have as little as the TIB_Session created in
the thread, and the AV occurs.
(Yeah I know some of the stuff in here is bad coding practice, like the A.PM
and Sleep(1) combo. I wouldn't normally do such things - this is just a
throwaway test app.)
Any help would be greatly appreciated. Thanks!
unit Unit22;
interface
uses
Forms, Controls, StdCtrls, Classes, ExtCtrls;
type
TForm22 = class(TForm)
Panel1: TPanel;
Button1: TButton;
LB: TListBox;
procedure Button1Click(Sender: TObject);
end;
var
Form22: TForm22;
implementation
{$R *.dfm}
uses
Windows, SysUtils, IB_Components, SyncObjs;
const
MAX_THREADS = 10;
type
TIBTestThread = class(TThread)
private
FDBSession: TIB_Session;
FDBConnection: TIB_Connection;
FDBTransaction: TIB_Transaction;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
var
KeepGoing: Boolean;
TotalThreads: Cardinal;
CS: TCriticalSection;
constructor TIBTestThread.Create;
begin
inherited Create(False);
FreeOnTerminate := True;
FDBSession := TIB_Session.Create(nil);
FDBConnection := TIB_Connection.Create(FDBSession);
FDBConnection.IB_Session := FDBSession;
FDBConnection.Path := ExtractFilePath(ParamStr(0)) + 'foo.fdb';
FDBConnection.Username := 'foo';
FDBConnection.Password := 'bar';
FDBConnection.Connect;
FDBTransaction := TIB_Transaction.Create(FDBSession);
FDBTransaction.IB_Connection := FDBConnection;
end;
destructor TIBTestThread.Destroy;
begin
CS.Enter;
try
Dec(TotalThreads);
finally
CS.Leave;
end;
FDBTransaction.Free;
FDBConnection.Disconnect;
FDBConnection.Free;
FDBSession.Free;
inherited;
end;
procedure TIBTestThread.Execute;
var
Cursor: TIB_Cursor;
begin
Cursor := TIB_Cursor.Create(FDBSession);
try
Cursor.IB_Transaction := FDBTransaction;
Cursor.SQL.Text :=
'select ' +
' RDB$RELATION_NAME ' +
'from ' +
' RDB$RELATIONS';
Cursor.Open;
try
while not Cursor.Eof do
begin
Cursor.Next;
end;
finally
Cursor.Close;
end;
finally
Cursor.Free;
end;
Terminate;
end;
procedure TForm22.Button1Click(Sender: TObject);
var
StillThreads: Boolean;
begin
try
if Button1.Caption <> 'Go' then
begin
KeepGoing := False;
Exit;
end;
Button1.Caption := 'Stop';
try
CS := TCriticalSection.Create;
try
Button1.Enabled := False;
try
TotalThreads := 0;
KeepGoing := True;
finally
Button1.Enabled := True;
end;
while KeepGoing do
begin
CS.Enter;
try
if TotalThreads < MAX_THREADS then
begin
TIBTestThread.Create;
Inc(TotalThreads);
end;
finally
CS.Leave;
end;
Application.ProcessMessages;
Sleep(1);
end;
Button1.Enabled := False;
try
repeat
CS.Enter;
try
StillThreads := TotalThreads > 0;
finally
CS.Leave;
end;
Application.ProcessMessages;
Sleep(1);
until not StillThreads;
finally
Button1.Enabled := True;
end;
finally
CS.Free;
end;
finally
Button1.Caption := 'Go';
end;
except
on E:Exception do
begin
OutputDebugString(PChar('EXCEPTION - ' + E.ClassType.ClassName + ' - ' +
E.Message));
end;
end;
end;
end.
--
Toby