ADO多線程數據庫查詢通常會出現3個問題:1、CoInitialize 沒有調用 (CoInitialize was not called);所以,在使用任何dbGo對象前,必須手 調用CoInitialize和CoUninitialize。調用CoInitialize失敗會產生"CoInitialize was not called"例外。2、畫布不允許繪畫 (Canvas does not allow drawing);所以,必須通過Synchronize過程來通知主線程訪問主窗體上的任何控件。3、不能使用主ADO連接 (Main TADoConnection cannot be used!);所以,線程中不能使用主線程中TADOConnection對象,每個線程必須創建自己的數據庫連接。Delphi2007安裝后在X:/Program Files/Common Files/CodeGear Shared/Data目錄下有一個dbdemos.mdb文件,用來作為測試的例子。dbdemos.mdb中的customer表保存了客戶信 息,orders表中保存了訂單信息。測試程序流程大致是這樣的:在主窗體上放TADOConnection和TQuery控件,啟動時這個TQuery從Customer表中查出客戶編碼 CustNo和公司名稱Company,放到三個Combox框中,分別在三個列表框中選定客戶公司名稱,按照公司名稱所對應的客戶代碼建立三個線程同時 在orders表中查詢銷售日期SaleDate分別填入ListBox中unitMain;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs,DB, ADODB, StdCtrls;typeTForm2 =class (TForm)ComboBox1: TComboBox;ComboBox2: TComboBox;ComboBox3: TComboBox;ListBox1: TListBox;ListBox2: TListBox;ListBox3: TListBox;Button1: TButton;ADOConnection1: TADOConnection;ADOQuery1: TADOQuery;Label1: TLabel;Label2: TLabel;Label3: TLabel;procedure FormCreate(Sender: TObject) ;procedure Button1Click(Sender: TObject) ;private{ Private declarations }public{ Public declarations }end ; varForm2: TForm2; implementationusesADOThread;{$R *.dfm}procedure TForm2.Button1Click(Sender: TObject); constSQL_CONST= 'Select SaleDate from orders where CustNo = %d' ; varc1,c2,c3: Integer ;s1, s2,s3: string ; begin//取得三個選擇框客戶的編碼 c1:= Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);c2:= Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);c3:= Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]);//生成SQL 查詢語句s1:=Format(SQL_CONST,[c1]);s2:=Format(SQL_CONST,[c2]);s3:=Format(SQL_CONST,[c3]);//三個線程同時查詢 TADOThread.Create(s1,ListBox1,Label1) ;TADOThread.Create(s2,ListBox2,Label2);TADOThread.Create(s3,ListBox3,Label3); end ;procedure TForm2.FormCreate(Sender: TObject); varstrSQL:string ; beginstrSQL:='SELECT CustNo,Company FROM customer';ADOQuery1.Close;ADOQuery1.SQL.Clear;ADOQuery1.SQL.Add(strSQL);ADOQuery1.Open;ComboBox1.Clear;ComboBox2.Clear;ComboBox3.Clear;//將客戶Company和相關CustNo填到ComboBox中while not ADOQuery1.Eof dobeginComboBox1.AddItem(ADOQuery1.Fields[1].asString, TObject(ADOQuery1.Fields[0].AsInteger));ADOQuery1.Next;end ;ComboBox2.Items.Assign(ComboBox1.Items);ComboBox3.Items.Assign(ComboBox1.Items);// 默認選中第一個ComboBox1.ItemIndex := 0;ComboBox2.ItemIndex := 0;ComboBox3.ItemIndex := 0; end ;end. {ADO查詢多線程單元}unitADOThread;interfaceusesClasses,StdCtrls,ADODB; typeTADOThread = class(TThread)private{ Private declarations }FListBox:TListBox;FLabel:TLabel;ConnString:WideString;FSQLString:string;procedure UpdateCount;protectedprocedure Execute; override;publicconstructor Create(SQL:string;LB:TListBox;Lab:TLabel);end ;implementationuses Main,SysUtils,ActiveX;{ TADOThread }constructor TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel); beginConnString:=Form2.ADOConnection1.ConnectionString;FListBox:=LB;FLabel:=Lab;FSQLString:=SQL;Inherited Create(False); end ;procedure TADOThread.Execute; varQry:TADOQuery;i:Integer; begin{ Place thread code here }FreeOnTerminate:=True;CoInitialize(nil);//必須調用(需Uses ActiveX)Qry:=TADOQuery.Create(nil);tryQry.ConnectionString:=ConnString; //必須有自己的連接 Qry.Close;Qry.SQL.Clear;Qry.SQL.Add(FSQLString);Qry.Open;FListBox.Clear;for i := 0 to 100 do //為了執行久點重復歷遍數據集101次beginwhile not Qry.Eof And not Terminated dobeginFListBox.AddItem(Qry.Fields[0].asstring,nil);//如果不調用Synchronize,會出現Canvas Does NOT Allow Drawing Synchronize(UpdateCount);Qry.Next;end ;Qry.First;FListBox.AddItem('*******',nil);end ;finallyQry.Free;end ;CoUninitialize; end ;procedure TADOThread.UpdateCount; beginFLabel.Caption:=IntToStr(FListBox.Items.Count); end ;end.
?