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对象,每个线程必须创建自己的数据库连接。 Delphi安装后在X:/Program Files/Common Files/CodeGear Shared/Data目录下有一个dbdemos.mdb文件,用来作为测试的例子。dbdemos.mdb中的customer表保存了客户信 息,orders表中保存了订单信息。 测试程序流程大致是这样的:在主窗体上放TADOConnection和TQuery控件,启动时这个TQuery从Customer表中查出客户编码 CustNo和公司名称Company,放到三个Combox框中,分别在三个列表框中选定客户公司名称,按照公司名称所对应的客户代码建立三个线程同时 在orders表中查询销售日期SaleDate分别填入ListBox中unit Main;interfaceuses 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;implementationuses 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 //取得三个选择框客户的编码 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);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和相关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); // 默认选中第一个 ComboBox1.ItemIndex := 0; ComboBox2.ItemIndex := 0; ComboBox3.ItemIndex := 0;end ;end.{ADO查询多线程单元}unit ADOThread;interfaceuses 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 ;implementationuses 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); //必须调用(需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 //为了执行久点重复历遍数据集101次 begin while not Qry.Eof And not Terminated do begin FListBox.AddItem(Qry.Fields[0].asstring,nil); //如果不调用Synchronize,会出现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.
如果觉得《ADO多线程数据库查询》对你有帮助,请点赞、收藏,并留下你的观点哦!