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中。
-
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
-
-
public
-
-
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
-
-
c1:=Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);
-
c2:=Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);
-
c3:=Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]);
-
- 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;
-
-
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.
-
unit ADOThread;
-
-
interface
-
-
uses
- Classes,StdCtrls,ADODB;
-
-
type
-
TADOThread = class(TThread)
-
private
-
- 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;
-
-
-
-
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
-
- FreeOnTerminate:=True;
-
CoInitialize(nil);
-
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
-
begin
-
while not Qry.Eof And not Terminated do
-
begin
-
FListBox.AddItem(Qry.Fields[0].asstring,nil);
-
- 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.
程序运行结果如下:
可以看到三个线程同时执行。第一第三两个线程条件一样,查询的结果也一样。
|
请发表评论