zoukankan      html  css  js  c++  java
  • 【转】Delphi多线程学习(9):多线程数据库查询(ADO)

    原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html

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

      {主窗体代码}  

    1. unit Main;  
    2.    
    3. interface  
    4.    
    5. uses  
    6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
    7.   Dialogs, DB, ADODB, StdCtrls;  
    8.    
    9. type  
    10.   TForm2 = class(TForm)  
    11.     ComboBox1: TComboBox;  
    12.     ComboBox2: TComboBox;  
    13.     ComboBox3: TComboBox;  
    14.     ListBox1: TListBox;  
    15.     ListBox2: TListBox;  
    16.     ListBox3: TListBox;  
    17.     Button1: TButton;  
    18.     ADOConnection1: TADOConnection;  
    19.     ADOQuery1: TADOQuery;  
    20.     Label1: TLabel;  
    21.     Label2: TLabel;  
    22.     Label3: TLabel;  
    23.     procedure FormCreate(Sender: TObject);  
    24.     procedure Button1Click(Sender: TObject);  
    25.   private  
    26.     { Private declarations }  
    27.   public  
    28.     { Public declarations }  
    29.   end;  
    30.    
    31. var  
    32.   Form2: TForm2;  
    33.    
    34. implementation  
    35.    
    36. uses ADOThread;  
    37.    
    38. {$R *.dfm}  
    39.    
    40. procedure TForm2.Button1Click(Sender: TObject);  
    41. const  
    42.   SQL_CONST='Select SaleDate from orders where CustNo = %d';  
    43. var  
    44.   c1,c2,c3:Integer;  
    45.   s1,s2,s3:string;  
    46. begin  
    47.   //取得三个选择框客户的编码   
    48.   c1:=Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);  
    49.   c2:=Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);  
    50.   c3:=Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]);  
    51.   //生成SQL 查询语句   
    52.   s1:=Format(SQL_CONST,[c1]);  
    53.   s2:=Format(SQL_CONST,[c2]);  
    54.   s3:=Format(SQL_CONST,[c3]);  
    55.   //三个线程同时查询   
    56.   TADOThread.Create(s1,ListBox1,Label1);  
    57.   TADOThread.Create(s2,ListBox2,Label2);  
    58.   TADOThread.Create(s3,ListBox3,Label3);  
    59. end;  
    60.    
    61. procedure TForm2.FormCreate(Sender: TObject);  
    62. var  
    63.   strSQL:string;  
    64. begin  
    65.   strSQL:='SELECT CustNo,Company FROM customer';  
    66.   ADOQuery1.Close;  
    67.   ADOQuery1.SQL.Clear;  
    68.   ADOQuery1.SQL.Add(strSQL);  
    69.   ADOQuery1.Open;  
    70.   ComboBox1.Clear;  
    71.   ComboBox2.Clear;  
    72.   ComboBox3.Clear;  
    73.   //将客户Company和相关CustNo填到ComboBox中   
    74.   while not ADOQuery1.Eof do  
    75.   begin  
    76.     ComboBox1.AddItem(ADOQuery1.Fields[1].asString,  
    77.         TObject(ADOQuery1.Fields[0].AsInteger));  
    78.     ADOQuery1.Next;  
    79.   end;  
    80.   ComboBox2.Items.Assign(ComboBox1.Items);  
    81.   ComboBox3.Items.Assign(ComboBox1.Items);  
    82.   // 默认选中第一个   
    83.   ComboBox1.ItemIndex := 0;  
    84.   ComboBox2.ItemIndex := 0;  
    85.   ComboBox3.ItemIndex := 0;  
    86. end;  
    87.    
    88. end.{ADO查询多线程单元}  
    89. unit ADOThread;  
    90.    
    91. interface  
    92.    
    93. uses  
    94.   Classes,StdCtrls,ADODB;  
    95.    
    96. type  
    97.   TADOThread = class(TThread)  
    98.   private  
    99.     { Private declarations }  
    100.     FListBox:TListBox;  
    101.     FLabel:TLabel;  
    102.     ConnString:WideString;  
    103.     FSQLString:string;  
    104.     procedure UpdateCount;  
    105.   protected  
    106.     procedure Execute; override;  
    107.   public  
    108.     constructor Create(SQL:string;LB:TListBox;Lab:TLabel);  
    109.   end;  
    110.    
    111. implementation  
    112.    
    113. uses Main,SysUtils,ActiveX;  
    114.    
    115. { TADOThread }  
    116.    
    117. constructor TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel);  
    118. begin  
    119.   ConnString:=Form2.ADOConnection1.ConnectionString;  
    120.   FListBox:=LB;  
    121.   FLabel:=Lab;  
    122.   FSQLString:=SQL;  
    123.   Inherited Create(False);  
    124. end;  
    125.    
    126. procedure TADOThread.Execute;  
    127. var  
    128.   Qry:TADOQuery;  
    129.   i:Integer;  
    130. begin  
    131.   { Place thread code here }  
    132.   FreeOnTerminate:=True;  
    133.   CoInitialize(nil);  //必须调用(需Uses ActiveX)   
    134.   Qry:=TADOQuery.Create(nil);  
    135.   try  
    136.     Qry.ConnectionString:=ConnString;   //必须有自己的连接   
    137.     Qry.Close;  
    138.     Qry.SQL.Clear;  
    139.     Qry.SQL.Add(FSQLString);  
    140.     Qry.Open;  
    141.     FListBox.Clear;  
    142.     for i := to 100 do  //为了执行久点重复历遍数据集101次   
    143.       begin  
    144.         while not Qry.Eof And not Terminated do  
    145.         begin  
    146.           FListBox.AddItem(Qry.Fields[0].asstring,nil);  
    147.           //如果不调用Synchronize,会出现Canvas Does NOT Allow Drawing   
    148.           Synchronize(UpdateCount);  
    149.           Qry.Next;  
    150.         end;  
    151.         Qry.First;  
    152.         FListBox.AddItem('*******',nil);  
    153.       end;  
    154.   finally  
    155.     Qry.Free;  
    156.   end;  
    157.   CoUninitialize;  
    158. end;  
    159.    
    160. procedure TADOThread.UpdateCount;  
    161. begin  
    162.   FLabel.Caption:=IntToStr(FListBox.Items.Count);  
    163. end;  
    164.    
    165. end.  

    程序运行结果如下:

    可以看到三个线程同时执行。第一第三两个线程条件一样,查询的结果也一样。

  • 相关阅读:
    Canvas基础讲义
    封装一个DivTag
    递归深拷贝
    构造函数的执行过程
    封装一个Ajax工具函数
    数组去重
    [js开源组件开发]js多选日期控件
    自己写的表格插件autotable
    复杂表格的树形结构的添加删除行div实现
    自制html5塔防游戏
  • 原文地址:https://www.cnblogs.com/tc310/p/4838301.html
Copyright © 2011-2022 走看看