Can someone tell me what this means..
I ran accesses against a global ADO connection in a number of threads
such that the accesses would occur simultaneously, or at least would
overlap (this was a test program just to see if or how ADO would
handle it), with each thread recording the time it started
and completed and needing to iterate through a large table for the
sake of taking up some time to cause overlap.
The results showed that the threads would not overlap.
That is, each start time was later than the previous thread's stop
time.
Here's the Execute procedure that I used:
procedure TTestThread.Execute;
var
~ rst: ADODB_TLB.Recordset;
~ lngAffected: OLEVariant;
~ strName: string;
begin
~ Self.start := Loword(GetTickCount);
~ rst := cnn.Execute('SELECT * FROM Customers;', lngAffected,
adCmdText);
// Just loop through about 600 records or so (takes ~15ms)
~ while not rst.EOF do
~ begin
~~~ strName := rst.Fields.Item['FirstName'].Value;
~~~ rst.MoveNext;
~ end;
~ rst.Close;
~ Self.stop := Loword(GetTickCount);
end;
Five threads where launched at the same time like this:
procedure TForm1.Button1Click(Sender: TObject);
var
~ thrdAcc: TTestThread;
~ i: integer;
begin
~ ListBox1.AddItem(Format('Button Clicked: %d', [LoWord
(GetTickCount)]), Nil);
~ for i := 1 to 5 do
~ begin
~~~ thrdAcc := TTesthread.Create(True);
~~~ thrdAcc.FreeOnTerminate := True;
~~~ thrdAcc.id := i;
~~~ thrdAcc.OnTerminate := Self.ThreadDone;
// thrdAcc.cnn := cnn; {if testing using a local copy}
~ end;
~ Listbox1.AddItem(Format('Loop completed: %d', [Loword
(GetTickCount)]), Nil);
end;
procedure TForm1.ThreadDone(Sender: TObject);
var
~ thrd: TTestThread;
begin
~ thrd := Sender as TTestThread;
~ Listbox1.Items.Add(Format('id: %d; start: %d; stop: %d',
~~ [thrd.id, thrd.start, thrd.stop]));
end;
As you may have figured out from the above code, TTestThread is
defined like this:
type
~ TTestThread = class(TThread)
~ protected
~~~ procedure Execute; override;
~ public
~~~ id: integer;
~~~ start, stop: word;
// cnn: ADODB_TLB.Connection; // local copy
~ end;
The connection "cnn" is a global variable declared as
var
cnn: ADODB_TLB.Connection;
The connection is created and opened in FormCreate.
I've opened it as an exclusive connection, but even opening it as a
shared connection produced the same results.
procedure TForm1.FormCreate(Sender: TObject);
const
STR_CONNECT = 'Provider=Microsoft.Jet.OLEDB.4.0;' +
'Data Source=%s;Mode=Share Deny Read|Share Deny Write;';
var
~ strConnect: string;
begin
~ cnn := ADODB_TLB.CoConnection.Create;
~ strConnect := Format(STR_CONNECT, ['c:\myfile.mdb']);
~ cnn.Open(strConnect, 'Admin', '', adConnectUnspecified);
end;
The "Loop Completed" showed a time about the same as when Thread1
started.
But the "odd" results I am referring to is that Listbox1 showed that
Thread2 started only after Thread1 finished, and so on. This is not
the result I get if I replace the recordset opening -> closing code
with something simple like Sleep(100). In that case the next thread
can be seen to start BEFORE the previous thread has completed.
It's great that a single global ADO connection that has been opened
exclusively can handle accesses from multiple threads without
breaking.
But it seems to achieve this by "queuing up" the threads by itself.
Any comments?
Ian.