we're having a problem using the TUniQuery.BreakExec method (UniDAC 4.5.9) with PostgreSQL 8.4. While it works fine when using SQLite, with PG the call to TUniQuery.Open never returns if BreakExec gets called and the thread calling the Open method keeps running 'forever' at 100% load (keeping one CPU core busy).
I created a simple demo project to reproduce the problem:
- GUI sets up TUniQuery/TUniConnection and a worker thread (TThread descendant) and passes a reference to the UniQuery object to the thread, then resumes the thread.
- Thread does nothing except calling UniQuery.Open (so as soon as Open returns the thread finishes)
- the GUI thread uses MsgWaitForMultipleObjects to wait for the thread to finish and then displays the resulting data set in a grid
- on the form there is a button which can be used to call UniQuery.BreakExec (again using a reference of the same query instance passed to the worker thread)
Worker thread:
Code: Select all
interface
TQueryThread = Class(TThread)
private
fQuery : TUniQuery;
protected
procedure Execute; override;
public
constructor Create(aQuery : TUniQuery); reintroduce;
property Query : TUniQuery
read fQuery;
End;
implementation
{ TQueryThread }
constructor TQueryThread.Create(aQuery: TUniQuery);
begin
inherited Create(true);
fQuery := aQuery;
end;
procedure TQueryThread.Execute;
begin
//The following Open call never returns if using PostgreSQL
//and BreakExec called while query running. This thread causes
//100% cpu load after BreakExec call (see form code below)
//SQLite works fine, though
fQuery.Open;
if fQuery.Fetched then
outputdebugstring('query completed')
else if fQuery.Fetching then
outputdebugstring('query aborted');
end;
Code: Select all
procedure TForm1.OpenQuery(aQuery: TUniQuery);
var
t: array of THandle;
n: Cardinal;
begin
//aQuery.SQL.Text = 'SELECT * FROM test'
worker := TQueryThread.Create(aQuery);
try
worker.Resume;
setLength(t, 1);
t[0] := worker.Handle;
while true do
begin
n := MsgWaitForMultipleObjects(length(t), t[0], false, INFINITE, QS_ALLINPUT);
case n of
WAIT_OBJECT_0: break;
else
Application.ProcessMessages;
end;
end;
finally
worker.Terminate;
worker.WaitFor;
FreeAndNil(worker);
end;
end;
procedure TForm1.btn_BreakExecClick(Sender: TObject);
begin
if Assigned(worker) then
//PostgreSQL: thread never finishes but causes 100% load after this call
worker.Query.BreakExec;
end;
I could upload the complete project somewhere if needed.