教程-Delphi多線程數據庫查詢(ADO)


ADO多線程數據庫查詢通常會出現以下問題:

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中。

4、COM接口調用時必須有線程自己的接口。

    如:在A線程建的COM接口,B線程調用時就提示“應用程序調用一個已為另一線程整理的接口”。這時只要在B線程建立自己獨有的COM接口使用就可以了。

 

 

 

 1 {主窗體代碼}
 2 unit Main;
 3 interface
 4   uses Windows, Messages, SysUtils, Variants,
 5     Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, StdCtrls;
 6 type
 7   TForm2 = class(TForm)
 8   ComboBox1: TComboBox;
 9   ComboBox2: TComboBox;
10   ComboBox3: TComboBox;
11   ListBox1: TListBox;
12   ListBox2: TListBox;
13   ListBox3: TListBox;
14   Button1: TButton;
15   ADOConnection1: TADOConnection;
16   ADOQuery1: TADOQuery; 
17   Label1: TLabel;
18   Label2: TLabel;
19   Label3: TLabel;
20   procedure FormCreate(Sender: TObject); 
21   procedure Button1Click(Sender: TObject);
22   private { Private declarations }
23   public { Public declarations }
24   end;
25 var Form2: TForm2;
26 implementation
27 uses
28   ADOThread;
29   {$R *.dfm}
30 
31 procedure TForm2.Button1Click(Sender: TObject);
32 const 
33   SQL_CONST='Select SaleDate from orders where CustNo = %d';
34   var c1,c2,c3:Integer; s1,s2,s3:string;
35 begin //取得三個選擇框客戶的編碼
36   c1:=Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);
37   c2:=Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);
38   c3:=Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]); //生成SQL 查詢語句
39   s1:=Format(SQL_CONST,[c1]);
40   s2:=Format(SQL_CONST,[c2]);
41   s3:=Format(SQL_CONST,[c3]); //三個線程同時查詢
42   TADOThread.Create(s1,ListBox1,Label1);
43   TADOThread.Create(s2,ListBox2,Label2);
44   TADOThread.Create(s3,ListBox3,Label3);
45 end;
46 
47 procedure TForm2.FormCreate(Sender: TObject);
48 var
49   strSQL:string;
50 begin
51   strSQL:='SELECT CustNo,Company FROM customer';
52   ADOQuery1.Close;
53   ADOQuery1.SQL.Clear;
54   ADOQuery1.SQL.Add(strSQL);
55   ADOQuery1.Open;
56   ComboBox1.Clear;
57   ComboBox2.Clear;
58   ComboBox3.Clear; //將客戶Company和相關CustNo填到ComboBox中
59   while not ADOQuery1.Eof do
60   begin
61     ComboBox1.AddItem(ADOQuery1.Fields[1].asString, TObject(ADOQuery1.Fields[0].AsInteger));
62     ADOQuery1.Next;
63   end;
64   ComboBox2.Items.Assign(ComboBox1.Items);
65   ComboBox3.Items.Assign(ComboBox1.Items); // 默認選中第一個
66   ComboBox1.ItemIndex := 0;
67   ComboBox2.ItemIndex := 0;
68   ComboBox3.ItemIndex := 0;
69 end;
70 end.

 

 

 1 {ADO查詢多線程單元}
 2 unit ADOThread;
 3 interface
 4 uses
 5   Classes,StdCtrls,ADODB;
 6 type TADOThread = class(TThread)
 7   private { Private declarations }
 8   FListBox:TListBox;
 9   FLabel:TLabel;
10   ConnString:WideString;
11   FSQLString:string;
12   procedure UpdateCount;
13   protected procedure Execute; override;
14   public constructor Create(SQL:string;LB:TListBox;Lab:TLabel);
15 end;
16 
17 implementation
18 uses
19   Main,SysUtils,ActiveX;
20   { TADOThread }
21 
22 constructor TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel);
23 begin
24   ConnString:=Form2.ADOConnection1.ConnectionString;
25   FListBox:=LB;
26   FLabel:=Lab;
27   FSQLString:=SQL;
28   Inherited Create(False);
29 end;
30 
31 procedure TADOThread.Execute;
32 var
33   Qry:TADOQuery;
34   i:Integer;
35 begin { Place thread code here }
36   FreeOnTerminate:=True;
37   CoInitialize(nil); //必須調用(需Uses ActiveX)
38   Qry:=TADOQuery.Create(nil);
39   try
40     Qry.ConnectionString:=ConnString; //必須有自己的連接
41     Qry.Close;
42     Qry.SQL.Clear;
43     Qry.SQL.Add(FSQLString);
44     Qry.Open;
45     FListBox.Clear;
46     for i := 0 to 100 do //為了執行久點重復歷遍數據集101次
47     begin
48       while not Qry.Eof And not Terminated do
49       begin
50         FListBox.AddItem(Qry.Fields[0].asstring,nil); //如果不調用Synchronize,會出現Canvas Does NOT Allow Drawing
51         Synchronize(UpdateCount);
52         Qry.Next;
53       end;
54       Qry.First;
55       FListBox.AddItem('*******',nil);
56     end;
57   finally
58     Qry.Free;
59   end;
60   CoUninitialize;
61 end;
62 
63 procedure TADOThread.UpdateCount;
64 begin
65   FLabel.Caption:=IntToStr(FListBox.Items.Count);
66 end;
67 end.

 

 

 

程序運行結果可以看到三個線程同時執行。第一第三兩個線程條件一樣,查詢的結果也一樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM