Delphi多线程学习:多线程数据库查询(ADO)

来源:互联网 发布:windows sass 编辑:程序博客网 时间:2024/06/05 22:34

  1. ADO多线程数据库查询通常会出现3个问题:  
  2.   
  3. 1、CoInitialize 没有调用 (CoInitialize was not called);所以,在使用任何dbGo对象前,必须手 调用CoInitialize和CoUninitialize。调用CoInitialize失败会产生"CoInitialize was not called"例外。  
  4.   
  5. 2、画布不允许绘画 (Canvas does not allow drawing);所以,必须通过Synchronize过程来通知主线程访问主窗体上的任何控件。  
  6.   
  7. 3、不能使用主ADO连接 (Main TADoConnection cannot be used!);所以,线程中不能使用主线程中TADOConnection对象,每个线程必须创建自己的数据库连接。  
  8.   
  9.      Delphi2007安装后在X:/Program Files/Common Files/CodeGear Shared/Data目录下有一个dbdemos.mdb文件,用来作为测试的例子。dbdemos.mdb中的customer表保存了客户信 息,orders表中保存了订单信息。  
  10.   
  11.        测试程序流程大致是这样的:在主窗体上放TADOConnection和TQuery控件,启动时这个TQuery从Customer表中查出客户编码 CustNo和公司名称Company,放到三个Combox框中,分别在三个列表框中选定客户公司名称,按照公司名称所对应的客户代码建立三个线程同时 在orders表中查询销售日期SaleDate分别填入ListBox中  
  12.   
  13. unit  
  14.  Main;  
  15.   
  16. interface  
  17.   
  18. uses  
  19.   Windows,  Messages,  SysUtils,   Variants, Classes, Graphics,   Controls, Forms,   Dialogs,  
  20.  DB,       ADODB,      StdCtrls;  
  21.   
  22. type  
  23.   TForm2 =class (TForm)  
  24.     ComboBox1:  TComboBox;  
  25.     ComboBox2:  TComboBox;  
  26.     ComboBox3:   TComboBox;  
  27.     ListBox1:    TListBox;  
  28.     ListBox2:   TListBox;  
  29.     ListBox3:    TListBox;  
  30.     Button1:  TButton;  
  31.     ADOConnection1:  TADOConnection;  
  32.     ADOQuery1:  TADOQuery;  
  33.     Label1: TLabel;  
  34.     Label2:  TLabel;  
  35.     Label3: TLabel;  
  36.   
  37.     procedure  FormCreate(Sender: TObject) ;  
  38.     procedure  Button1Click(Sender: TObject) ;  
  39.   private  
  40.     { Private declarations }  
  41.   public  
  42.     { Public declarations }  
  43.   end    ;  
  44. var  
  45.   Form2:    TForm2;  
  46. implementation  
  47.   
  48. uses  
  49.  ADOThread;  
  50.   
  51. {$R *.dfm}  
  52.   
  53. procedure   TForm2.Button1Click(Sender: TObject);  
  54. const  
  55.   SQL_CONST= 'Select SaleDate from orders where CustNo = %d' ;  
  56. var  
  57.   c1,c2,c3: Integer  ;  
  58.   s1, s2,s3: string ;  
  59. begin  
  60.   
  61.   //取得三个选择框客户的编码  
  62.   
  63.   c1:= Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);  
  64.   c2:= Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);  
  65.   c3:= Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]);  
  66.   //生成SQL 查询语句  
  67.   s1:=Format(SQL_CONST,[c1]);  
  68.   s2:=Format(SQL_CONST,[c2]);  
  69.   s3:=Format(SQL_CONST,[c3]);  
  70.   //三个线程同时查询  
  71.   TADOThread.Create(s1,ListBox1,Label1) ;  
  72.   TADOThread.Create(s2,ListBox2,Label2);  
  73.   TADOThread.Create(s3,ListBox3,Label3);  
  74. end ;  
  75.   
  76. procedure TForm2.FormCreate(Sender: TObject);  
  77. var  
  78.   strSQL:string ;  
  79. begin  
  80.   strSQL:='SELECT CustNo,Company FROM customer';  
  81.   ADOQuery1.Close;  
  82.   ADOQuery1.SQL.Clear;  
  83.   ADOQuery1.SQL.Add(strSQL);  
  84.   ADOQuery1.Open;  
  85.   ComboBox1.Clear;  
  86.   ComboBox2.Clear;  
  87.   ComboBox3.Clear;  
  88.   //将客户Company和相关CustNo填到ComboBox中  
  89.   while  not  ADOQuery1.Eof  do  
  90.   begin  
  91.     ComboBox1.AddItem(ADOQuery1.Fields[1].asString, TObject(ADOQuery1.Fields[0].AsInteger));  
  92.     ADOQuery1.Next;  
  93.   end ;  
  94.   ComboBox2.Items.Assign(ComboBox1.Items);  
  95.   ComboBox3.Items.Assign(ComboBox1.Items);  
  96.   // 默认选中第一个  
  97.   ComboBox1.ItemIndex := 0;  
  98.   ComboBox2.ItemIndex := 0;  
  99.   ComboBox3.ItemIndex := 0;  
  100. end ;  
  101.   
  102. end.  
  103. {ADO查询多线程单元}  
  104.   
  105.   
  106. unit  
  107.  ADOThread;  
  108.   
  109. interface  
  110.   
  111. uses  
  112.   Classes,StdCtrls,ADODB;  
  113. type  
  114.   TADOThread = class(TThread)  
  115.   private  
  116.     { Private declarations }  
  117.     FListBox:TListBox;  
  118.     FLabel:TLabel;  
  119.     ConnString:WideString;  
  120.     FSQLString:string;  
  121.     procedure  UpdateCount;  
  122.   protected  
  123.     procedure  Execute; override;  
  124.   public  
  125.     constructor  Create(SQL:string;LB:TListBox;Lab:TLabel);  
  126.   end   ;  
  127.   
  128. implementation  
  129.   
  130. uses  Main,SysUtils,ActiveX;  
  131.   
  132. { TADOThread }  
  133.   
  134. constructor  TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel);  
  135. begin  
  136.   ConnString:=Form2.ADOConnection1.ConnectionString;  
  137.   FListBox:=LB;  
  138.     FLabel:=Lab;  
  139.   FSQLString:=SQL;  
  140.   Inherited  Create(False);  
  141. end  ;  
  142.   
  143. procedure  TADOThread.Execute;  
  144. var  
  145.   Qry:TADOQuery;  
  146.   i:Integer;  
  147. begin  
  148.   { Place thread code here }  
  149.   FreeOnTerminate:=True;  
  150.   CoInitialize(nil);  
  151.     //必须调用(需Uses ActiveX)  
  152.   Qry:=TADOQuery.Create(nil);  
  153.   try  
  154.     Qry.ConnectionString:=ConnString;   //必须有自己的连接  
  155.     Qry.Close;  
  156.     Qry.SQL.Clear;  
  157.     Qry.SQL.Add(FSQLString);  
  158.     Qry.Open;  
  159.     FListBox.Clear;  
  160.     for  i := 0 to 100 do     //为了执行久点重复历遍数据集101次  
  161.       begin  
  162.         while  not Qry.Eof And  not Terminated do  
  163.         begin  
  164.         FListBox.AddItem(Qry.Fields[0].asstring,nil);  
  165.           //如果不调用Synchronize,会出现Canvas Does NOT Allow Drawing  
  166.           Synchronize(UpdateCount);  
  167.           Qry.Next;  
  168.         end ;  
  169.         Qry.First;  
  170.         FListBox.AddItem('*******',nil);  
  171.       end ;  
  172.   finally  
  173.     Qry.Free;  
  174.   end ;  
  175.   CoUninitialize;  
  176. end  ;  
  177.   
  178. procedure   TADOThread.UpdateCount;  
  179. begin  
  180.   FLabel.Caption:=IntToStr(FListBox.Items.Count);  
  181. end     ;  
  182.   
  183. end.  
0 0