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