There are 3 problems with ADO multithreaded database queries:
1. CoInitialize is not called (CoInitialize is not called), so you must call CoInitialize and CoUninitialize before using any Dbgo object. Failure to invoke CoInitialize results in an exception of "CoInitialize is not called".
2. Canvas is not allowed to paint (canvas does not allow drawing); Therefore, the main thread must be notified through the synchronize process to access any control on the master form.
3. You cannot use the main ADO connection (main tadoconnection cannot be used!); Therefore, threads cannot use tadoconnection objects in the main thread, and each thread must create its own database connection.
Delphi2007 after installation there is a Shared\data file in the X:\Program Files\Common Files\codegear Dbdemos.mdb directory, which is used as an example of testing. The Customer table in Dbdemos.mdb holds the client information, and the order information is saved in the Orders table.
The test program flow is basically this: put the tadoconnection and Tquery controls on the main form, and at startup this tquery isolate the customer code CUSTNO and company name from the Customers table, put it in three combox boxes, Select the customer company name in three list boxes, establish three threads according to the customer code corresponding to the company name, and query the sales date in the Orders table Saledate respectively into the listbox.
1 {main form Code}2 UnitMain;3 Interface4 usesWindows, Messages, sysutils, variants,5 Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, Stdctrls;6 type7TForm2 =class(Tform)8 Combobox1:tcombobox;9 Combobox2:tcombobox;Ten Combobox3:tcombobox; One Listbox1:tlistbox; A Listbox2:tlistbox; - Listbox3:tlistbox; - Button1:tbutton; the adoconnection1:tadoconnection; - Adoquery1:tadoquery; - Label1:tlabel; - Label2:tlabel; + Label3:tlabel; - procedureformcreate (sender:tobject); + procedureButton1Click (sender:tobject); A Private {Private Declarations} at Public {Public Declarations} - End; - varForm2:tform2; - Implementation - uses - Adothread; in {$R *.DFM} - to procedureTform2.button1click (sender:tobject); + Const -sql_const='Select saledate from orders where Custno =%d'; the varC1,c2,c3:integer; S1,S2,S3:string; * begin //get three selection box customer's code $c1:=Integer (Combobox1.items.objects[combobox1.itemindex]);Panax Notoginsengc2:=Integer (Combobox2.items.objects[combobox2.itemindex]); -C3:=integer (Combobox3.items.objects[combobox3.itemindex]);//Generating SQL query Statements thes1:=Format (Sql_const,[c1]); +s2:=Format (SQL_CONST,[C2]); AS3:=format (SQL_CONST,[C3]);//three threads querying at the same time the tadothread.create (S1,LISTBOX1,LABEL1); + tadothread.create (S2,LISTBOX2,LABEL2); - tadothread.create (S3,LISTBOX3,LABEL3); $ End; $ - proceduretform2.formcreate (sender:tobject); - var thestrSQL:string; - beginWuyistrsql:='SELECT Custno,company from Customer'; the Adoquery1.close; - ADOQuery1.SQL.Clear; Wu ADOQuery1.SQL.Add (strSQL); - Adoquery1.open; About combobox1.clear; $ combobox2.clear; -Combobox3.clear;//fill in the ComboBox with customer company and related Custno - while notAdoquery1.eof Do - begin AComboBox1.AddItem (adoquery1.fields[1].asstring, TObject (adoquery1.fields[0]. Asinteger)); + Adoquery1.next; the End; - ComboBox2.Items.Assign (combobox1.items); $ComboBox3.Items.Assign (Combobox1.items);//The first one is selected by default theCombobox1.itemindex: =0; theCombobox2.itemindex: =0; theCombobox3.itemindex: =0; the End; - End.
1 {ADO Querying multithreaded units}2 UnitAdothread;3 Interface4 uses5 Classes,stdctrls,adodb;6 typeTadothread =class(TThread)7 Private {Private Declarations}8 Flistbox:tlistbox;9 Flabel:tlabel;Ten connstring:widestring; OneFsqlstring:string; A procedureUpdatecount; - protected procedureExecute;Override; - Public ConstructorCreate (SQL:string; lb:tlistbox; Lab:tlabel); the End; - - Implementation - uses + Main,sysutils,activex; - {Tadothread} + A ConstructorTadothread.create (SQL:string; Lb:tlistbox; Lab:tlabel); at begin -connstring:=Form2.ADOConnection1.ConnectionString; -flistbox:=LB; -flabel:=Lab; -fsqlstring:=SQL; - inherited Create (False); in End; - to procedureTadothread.execute; + var - Qry:tadoquery; the I:integer; * begin {Place Thread code here} $freeonterminate:=True;Panax NotoginsengCoInitialize (Nil);//must be called (requires uses ActiveX) -Qry:=tadoquery.create (Nil); the Try +qry.connectionstring:=connstring;//must have a connection of their own A Qry.close; the Qry.SQL.Clear; + Qry.SQL.Add (fsqlstring); - Qry.open; $ flistbox.clear; $ forI: =0 to - Do //repeat the data set 101 times in order to perform a long repetition. - begin - while notQry.eof and notTerminated Do the begin -Flistbox.additem (qry.fields[0].asstring,Nil);//If you do not call synchronize, the canvas Does not allow DrawingWuyi Synchronize (updatecount); the Qry.next; - End; Wu Qry.first; -Flistbox.additem ('*******',Nil); About End; $ finally - Qry.free; - End; - CoUninitialize; A End; + the procedureTadothread.updatecount; - begin $flabel.caption:=IntToStr (FListBox.Items.Count); the End; the End.
The results of the program run can see three threads executing simultaneously. The first 32 thread conditions are the same as the results of a query.
[Delphi Technology] Delphi Multi-Threaded database query (ADO)